LTP GCOV extension - code coverage report
Current view: directory - frmts/gxf - gxfopen.c
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 286
Code covered: 58.7 % Executed lines: 168

       1                 : /******************************************************************************
       2                 :  * $Id: gxfopen.c 19867 2010-06-14 20:45:06Z rouault $
       3                 :  *
       4                 :  * Project:  GXF Reader
       5                 :  * Purpose:  Majority of Geosoft GXF reading code.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 1998, Global Geomatics
      10                 :  * Copyright (c) 1998, Frank Warmerdam
      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 <ctype.h>
      32                 : #include "gxfopen.h"
      33                 : 
      34                 : CPL_CVSID("$Id: gxfopen.c 19867 2010-06-14 20:45:06Z rouault $");
      35                 : 
      36                 : 
      37                 : /* this is also defined in gdal.h which we avoid in this separable component */
      38                 : #define CPLE_WrongFormat  200
      39                 : 
      40                 : /************************************************************************/
      41                 : /*                         GXFReadHeaderValue()                         */
      42                 : /*                                                                      */
      43                 : /*      Read one entry from the file header, and return it and it's     */
      44                 : /*      value in clean form.                                            */
      45                 : /************************************************************************/
      46                 : 
      47                 : static char **GXFReadHeaderValue( FILE * fp, char * pszHTitle )
      48                 : 
      49              96 : {
      50                 :     const char  *pszLine;
      51              96 :     char  **papszReturn = NULL;
      52                 :     int   i;
      53                 :     
      54                 : /* -------------------------------------------------------------------- */
      55                 : /*      Try to read a line.  If we fail or if this isn't a proper       */
      56                 : /*      header value then return the failure.                           */
      57                 : /* -------------------------------------------------------------------- */
      58              96 :     pszLine = CPLReadLine( fp );
      59              96 :     if( pszLine == NULL )
      60                 :     {
      61               0 :         strcpy( pszHTitle, "#EOF" );
      62               0 :         return( NULL );
      63                 :     }
      64                 : 
      65                 : /* -------------------------------------------------------------------- */
      66                 : /*      Extract the title.  It should be terminated by some sort of     */
      67                 : /*      white space.                                                    */
      68                 : /* -------------------------------------------------------------------- */
      69              96 :     for( i = 0; !isspace((unsigned char)pszLine[i]) && pszLine[i] != '\0' && i < 70; i++ ) {}
      70                 : 
      71              96 :     strncpy( pszHTitle, pszLine, i );
      72              96 :     pszHTitle[i] = '\0';
      73                 : 
      74                 : /* -------------------------------------------------------------------- */
      75                 : /*      If this is #GRID, then return ... we are at the end of the      */
      76                 : /*      header.                                                         */
      77                 : /* -------------------------------------------------------------------- */
      78              96 :     if( EQUAL(pszHTitle,"#GRID") )
      79               7 :         return NULL;
      80                 : 
      81                 : /* -------------------------------------------------------------------- */
      82                 : /*      Skip white space.                                               */
      83                 : /* -------------------------------------------------------------------- */
      84            5433 :     while( isspace((unsigned char)pszLine[i]) )
      85            5255 :         i++;
      86                 : 
      87                 : /* -------------------------------------------------------------------- */
      88                 : /*    If we have reached the end of the line, try to read another line. */
      89                 : /* -------------------------------------------------------------------- */
      90              89 :     if( pszLine[i] == '\0' )
      91                 :     {
      92              89 :         pszLine = CPLReadLine( fp );
      93              89 :         if( pszLine == NULL )
      94                 :         {
      95               0 :             strcpy( pszHTitle, "#EOF" );
      96               0 :             return( NULL );
      97                 :         }
      98              89 :         i = 0;
      99                 :     }
     100                 : 
     101                 : /* -------------------------------------------------------------------- */
     102                 : /*      Keeping adding the value stuff as new lines till we reach a     */
     103                 : /*      `#' mark at the beginning of a new line.                        */
     104                 : /* -------------------------------------------------------------------- */
     105                 :     do {
     106                 :         int   nNextChar;
     107                 :         char    *pszTrimmedLine;
     108                 : 
     109             117 :         pszTrimmedLine = CPLStrdup( pszLine );
     110                 : 
     111            7364 :         for( i = strlen(pszLine)-1; i >= 0 && pszLine[i] == ' '; i-- ) 
     112            7247 :             pszTrimmedLine[i] = '\0';
     113                 :         
     114             117 :         papszReturn = CSLAddString( papszReturn, pszTrimmedLine );
     115             117 :         CPLFree( pszTrimmedLine );
     116                 :         
     117             117 :         nNextChar = VSIFGetc( fp );
     118             117 :         VSIUngetc( nNextChar, fp );
     119                 :         
     120             117 :         if( nNextChar == '#' )
     121              89 :             pszLine = NULL;
     122                 :         else
     123              28 :             pszLine = CPLReadLine( fp );
     124             117 :     } while( pszLine != NULL );
     125                 : 
     126              89 :     return( papszReturn );
     127                 : }
     128                 : 
     129                 : /************************************************************************/
     130                 : /*                              GXFOpen()                               */
     131                 : /************************************************************************/
     132                 : 
     133                 : /**
     134                 :  * Open a GXF file, and collect contents of the header.
     135                 :  *
     136                 :  * @param pszFilename the name of the file to open.
     137                 :  *
     138                 :  * @return a handle for use with other GXF functions to access the file.  This
     139                 :  * will be NULL if the access fails.
     140                 :  */
     141                 : 
     142                 : GXFHandle GXFOpen( const char * pszFilename )
     143                 : 
     144               7 : {
     145                 :     FILE  *fp;
     146                 :     GXFInfo_t *psGXF;
     147                 :     char  szTitle[71];
     148                 :     char  **papszList;
     149                 : 
     150                 : /* -------------------------------------------------------------------- */
     151                 : /*      We open in binary to ensure that we can efficiently seek()      */
     152                 : /*      to any location when reading scanlines randomly.  If we         */
     153                 : /*      opened as text we might still be able to seek(), but I          */
     154                 : /*      believe that on Windows, the C library has to read through      */
     155                 : /*      all the data to find the right spot taking into account DOS     */
     156                 : /*      CRs.                                                            */
     157                 : /* -------------------------------------------------------------------- */
     158               7 :     fp = VSIFOpen( pszFilename, "rb" );
     159                 : 
     160               7 :     if( fp == NULL )
     161                 :     {
     162                 :         /* how to effectively communicate this error out? */
     163               0 :         CPLError( CE_Failure, CPLE_OpenFailed,
     164                 :                   "Unable to open file: %s\n", pszFilename );
     165               0 :         return NULL;
     166                 :     }
     167                 : 
     168                 : /* -------------------------------------------------------------------- */
     169                 : /*      Create the GXF Information object.                              */
     170                 : /* -------------------------------------------------------------------- */
     171               7 :     psGXF = (GXFInfo_t *) VSICalloc( sizeof(GXFInfo_t), 1 );
     172               7 :     psGXF->fp = fp;
     173               7 :     psGXF->dfTransformScale = 1.0;
     174               7 :     psGXF->nSense = GXFS_LL_RIGHT;
     175               7 :     psGXF->dfXPixelSize = 1.0;
     176               7 :     psGXF->dfYPixelSize = 1.0;
     177               7 :     psGXF->dfSetDummyTo = -1e12;
     178                 : 
     179               7 :     psGXF->dfUnitToMeter = 1.0;
     180               7 :     psGXF->pszTitle = VSIStrdup("");
     181                 :     
     182                 : /* -------------------------------------------------------------------- */
     183                 : /*      Read the header, one line at a time.                            */
     184                 : /* -------------------------------------------------------------------- */
     185             103 :     while( (papszList = GXFReadHeaderValue( fp, szTitle)) != NULL )
     186                 :     {
     187              89 :         if( EQUALN(szTitle,"#TITL",5) )
     188                 :         {
     189               6 :             CPLFree( psGXF->pszTitle );
     190               6 :             psGXF->pszTitle = CPLStrdup( papszList[0] );
     191                 :         }
     192              83 :         else if( EQUALN(szTitle,"#POIN",5) )
     193                 :         {
     194               7 :             psGXF->nRawXSize = atoi(papszList[0]);
     195                 :         }
     196              76 :         else if( EQUALN(szTitle,"#ROWS",5) )
     197                 :         {
     198               7 :             psGXF->nRawYSize = atoi(papszList[0]);
     199                 :         }
     200              69 :         else if( EQUALN(szTitle,"#PTSE",5) )
     201                 :         {
     202               6 :             psGXF->dfXPixelSize = atof(papszList[0]);
     203                 :         }
     204              63 :         else if( EQUALN(szTitle,"#RWSE",5) )
     205                 :         {
     206               6 :             psGXF->dfYPixelSize = atof(papszList[0]);
     207                 :         }
     208              57 :         else if( EQUALN(szTitle,"#DUMM",5) )
     209                 :         {
     210               2 :             memset( psGXF->szDummy, 0, sizeof(psGXF->szDummy));
     211               2 :             strncpy( psGXF->szDummy, papszList[0], sizeof(psGXF->szDummy) - 1);
     212               2 :             psGXF->dfSetDummyTo = atof(papszList[0]);
     213                 :         }
     214              55 :         else if( EQUALN(szTitle,"#XORI",5) )
     215                 :         {
     216               6 :             psGXF->dfXOrigin = atof(papszList[0]);
     217                 :         }
     218              49 :         else if( EQUALN(szTitle,"#YORI",5) )
     219                 :         {
     220               6 :             psGXF->dfYOrigin = atof(papszList[0]);
     221                 :         }
     222              43 :         else if( EQUALN(szTitle,"#ZMIN",5) )
     223                 :         {
     224               6 :             psGXF->dfZMinimum = atof(papszList[0]);
     225                 :         }
     226              37 :         else if( EQUALN(szTitle,"#ZMAX",5) )
     227                 :         {
     228               6 :             psGXF->dfZMaximum = atof(papszList[0]);
     229                 :         }
     230              31 :         else if( EQUALN(szTitle,"#SENS",5) )
     231                 :         {
     232               6 :             psGXF->nSense = atoi(papszList[0]);
     233                 :         }
     234              25 :         else if( EQUALN(szTitle,"#MAP_PROJECTION",8) )
     235                 :         {
     236               5 :             psGXF->papszMapProjection = papszList;
     237               5 :             papszList = NULL;
     238                 :         }
     239              20 :         else if( EQUALN(szTitle,"#MAP_D",5) )
     240                 :         {
     241               0 :             psGXF->papszMapDatumTransform = papszList;
     242               0 :             papszList = NULL;
     243                 :         }
     244              20 :         else if( EQUALN(szTitle,"#UNIT",5) )
     245                 :         {
     246                 :             char  **papszFields;
     247                 : 
     248               5 :             papszFields = CSLTokenizeStringComplex( papszList[0], ", ",
     249                 :                                                     TRUE, TRUE );
     250                 : 
     251               5 :             if( CSLCount(papszFields) > 1 )
     252                 :             {
     253               5 :                 psGXF->pszUnitName = VSIStrdup( papszFields[0] );
     254               5 :                 psGXF->dfUnitToMeter = atof( papszFields[1] );
     255               5 :                 if( psGXF->dfUnitToMeter == 0.0 )
     256               0 :                     psGXF->dfUnitToMeter = 1.0;
     257                 :             }
     258                 : 
     259               5 :             CSLDestroy( papszFields );
     260                 :         }
     261              15 :         else if( EQUALN(szTitle,"#TRAN",5) )
     262                 :         {
     263                 :             char  **papszFields;
     264                 : 
     265               5 :             papszFields = CSLTokenizeStringComplex( papszList[0], ", ",
     266                 :                                                     TRUE, TRUE );
     267                 : 
     268               5 :             if( CSLCount(papszFields) > 1 )
     269                 :             {
     270               5 :                 psGXF->dfTransformScale = atof(papszFields[0]);
     271               5 :                 psGXF->dfTransformOffset = atof(papszFields[1]);
     272                 :             }
     273                 : 
     274               5 :             if( CSLCount(papszFields) > 2 )
     275               0 :                 psGXF->pszTransformName = CPLStrdup( papszFields[2] );
     276                 : 
     277               5 :             CSLDestroy( papszFields );
     278                 :         }
     279              10 :         else if( EQUALN(szTitle,"#GTYPE",5) )
     280                 :         {
     281               4 :             psGXF->nGType = atoi(papszList[0]);
     282                 :         }
     283                 : 
     284              89 :         CSLDestroy( papszList );
     285                 :     }
     286                 : 
     287                 : /* -------------------------------------------------------------------- */
     288                 : /*      Did we find the #GRID?                                          */
     289                 : /* -------------------------------------------------------------------- */
     290               7 :     if( !EQUALN(szTitle,"#GRID",5) )
     291                 :     {
     292               0 :         GXFClose( psGXF );
     293               0 :         CPLError( CE_Failure, CPLE_WrongFormat,
     294                 :                   "Didn't parse through to #GRID successfully in.\n"
     295                 :                   "file `%s'.\n",
     296                 :                   pszFilename );
     297                 :         
     298               0 :         return NULL;
     299                 :     }
     300                 : 
     301                 : /* -------------------------------------------------------------------- */
     302                 : /*      Allocate, and initialize the raw scanline offset array.         */
     303                 : /* -------------------------------------------------------------------- */
     304               7 :     psGXF->panRawLineOffset = (long *)
     305                 :         CPLCalloc( sizeof(long), psGXF->nRawYSize+1 );
     306                 : 
     307               7 :     psGXF->panRawLineOffset[0] = VSIFTell( psGXF->fp );
     308                 : 
     309                 : /* -------------------------------------------------------------------- */
     310                 : /*      Update the zmin/zmax values to take into account #TRANSFORM     */
     311                 : /*      information.                                                    */
     312                 : /* -------------------------------------------------------------------- */
     313               7 :     if( psGXF->dfZMinimum != 0.0 || psGXF->dfZMaximum != 0.0 )
     314                 :     {
     315               6 :         psGXF->dfZMinimum = (psGXF->dfZMinimum * psGXF->dfTransformScale)
     316                 :                   + psGXF->dfTransformOffset;
     317               6 :         psGXF->dfZMaximum = (psGXF->dfZMaximum * psGXF->dfTransformScale)
     318                 :                   + psGXF->dfTransformOffset;
     319                 :     }
     320                 :     
     321               7 :     return( (GXFHandle) psGXF );
     322                 : }
     323                 : 
     324                 : /************************************************************************/
     325                 : /*                              GXFClose()                              */
     326                 : /************************************************************************/
     327                 : 
     328                 : /**
     329                 :  * Close GXF file opened with GXFOpen().
     330                 :  *
     331                 :  * @param hGXF handle to GXF file.
     332                 :  */
     333                 : 
     334                 : void GXFClose( GXFHandle hGXF )
     335                 : 
     336               7 : {
     337               7 :     GXFInfo_t *psGXF = (GXFInfo_t *) hGXF;
     338                 : 
     339               7 :     CPLFree( psGXF->panRawLineOffset );
     340               7 :     CPLFree( psGXF->pszUnitName );
     341               7 :     CSLDestroy( psGXF->papszMapDatumTransform );
     342               7 :     CSLDestroy( psGXF->papszMapProjection );
     343               7 :     CPLFree( psGXF->pszTitle );
     344               7 :     CPLFree( psGXF->pszTransformName );
     345                 : 
     346               7 :     VSIFClose( psGXF->fp );
     347                 : 
     348               7 :     CPLReadLine( NULL );
     349                 : 
     350               7 :     CPLFree( psGXF );
     351               7 : }
     352                 : 
     353                 : /************************************************************************/
     354                 : /*                           GXFParseBase90()                           */
     355                 : /*                                                                      */
     356                 : /*      Parse a base 90 number ... exceptions (repeat, and dummy)       */
     357                 : /*      values have to be recognised outside this function.             */
     358                 : /************************************************************************/
     359                 : 
     360                 : double GXFParseBase90( GXFInfo_t * psGXF, const char * pszText,
     361                 :                        int bScale )
     362                 : 
     363          477843 : {
     364          477843 :     int   i = 0, nValue = 0;
     365                 : 
     366         2867058 :     while( i < psGXF->nGType )
     367                 :     {
     368         1911372 :         nValue = nValue*90 + (pszText[i] - 37);
     369         1911372 :         i++;
     370                 :     }
     371                 : 
     372          477843 :     if( bScale ) 
     373          476828 :         return( (nValue * psGXF->dfTransformScale) + psGXF->dfTransformOffset);
     374                 :     else
     375            1015 :         return( nValue );
     376                 : }
     377                 : 
     378                 : 
     379                 : /************************************************************************/
     380                 : /*                       GXFReadRawScanlineFrom()                       */
     381                 : /************************************************************************/
     382                 : 
     383                 : static int GXFReadRawScanlineFrom( GXFInfo_t * psGXF, long iOffset,
     384                 :                                    long * pnNewOffset, double * padfLineBuf )
     385                 : 
     386            1530 : {
     387                 :     const char  *pszLine;
     388            1530 :     int   nValuesRead = 0, nValuesSought = psGXF->nRawXSize;
     389                 :     
     390            1530 :     VSIFSeek( psGXF->fp, iOffset, SEEK_SET );
     391                 : 
     392           41554 :     while( nValuesRead < nValuesSought )
     393                 :     {
     394           38494 :         pszLine = CPLReadLine( psGXF->fp );
     395           38494 :         if( pszLine == NULL )
     396               0 :             break;
     397                 : 
     398                 : /* -------------------------------------------------------------------- */
     399                 : /*      Uncompressed case.                                              */
     400                 : /* -------------------------------------------------------------------- */
     401           38494 :         if( psGXF->nGType == 0 )
     402                 :         {
     403                 :             /* we could just tokenize the line, but that's pretty expensive.
     404                 :                Instead I will parse on white space ``by hand''. */
     405          138216 :             while( *pszLine != '\0' && nValuesRead < nValuesSought )
     406                 :             {
     407                 :                 int   i;
     408                 :                 
     409                 :                 /* skip leading white space */
     410          110130 :                 for( ; isspace((unsigned char)*pszLine); pszLine++ ) {}
     411                 : 
     412                 :                 /* Skip the data value (non white space) */
     413          110130 :                 for( i = 0; pszLine[i] != '\0' && !isspace((unsigned char)pszLine[i]); i++) {}
     414                 : 
     415          110130 :                 if( strncmp(pszLine,psGXF->szDummy,i) == 0 )
     416                 :                 {
     417           17731 :                     padfLineBuf[nValuesRead++] = psGXF->dfSetDummyTo;
     418                 :                 }
     419                 :                 else
     420                 :                 {
     421           92399 :                     padfLineBuf[nValuesRead++] = atof(pszLine);
     422                 :                 }
     423                 : 
     424                 :                 /* skip further whitespace */
     425          110130 :                 for( pszLine += i; isspace((unsigned char)*pszLine); pszLine++ ) {}
     426                 :             }
     427                 :         }
     428                 : 
     429                 : /* -------------------------------------------------------------------- */
     430                 : /*      Compressed case.                                                */
     431                 : /* -------------------------------------------------------------------- */
     432                 :         else
     433                 :         {
     434          527977 :             while( *pszLine != '\0' && nValuesRead < nValuesSought )
     435                 :             {
     436          479075 :                 if( pszLine[0] == '!' )
     437                 :                 {
     438            1887 :                     padfLineBuf[nValuesRead++] = psGXF->dfSetDummyTo;
     439                 :                 }
     440          477188 :                 else if( pszLine[0] == '"' )
     441                 :                 {
     442                 :                     int   nCount, i;
     443                 :                     double  dfValue;
     444                 : 
     445            1015 :                     pszLine += psGXF->nGType;
     446            1015 :                     if( (int) strlen(pszLine) < psGXF->nGType )
     447              22 :                         pszLine = CPLReadLine( psGXF->fp );
     448                 :                     
     449            1015 :                     nCount = (int) GXFParseBase90( psGXF, pszLine, FALSE);
     450            1015 :                     pszLine += psGXF->nGType;
     451                 :                     
     452            1015 :                     if( (int) strlen(pszLine) < psGXF->nGType )
     453              34 :                         pszLine = CPLReadLine( psGXF->fp );
     454                 :                     
     455            1015 :                     if( *pszLine == '!' )
     456             360 :                         dfValue = psGXF->dfSetDummyTo;
     457                 :                     else
     458             655 :                         dfValue = GXFParseBase90( psGXF, pszLine, TRUE );
     459                 : 
     460            1015 :                     if( nValuesRead + nCount > nValuesSought )
     461                 :                     {
     462               0 :                         CPLError(CE_Failure, CPLE_AppDefined, "Wrong count value");
     463               0 :                         return CE_Failure;
     464                 :                     }
     465                 :                     
     466           25212 :                     for( i=0; i < nCount && nValuesRead < nValuesSought; i++ )
     467           24197 :                         padfLineBuf[nValuesRead++] = dfValue;
     468                 :                 }
     469                 :                 else
     470                 :                 {
     471          476173 :                     padfLineBuf[nValuesRead++] =
     472                 :                         GXFParseBase90( psGXF, pszLine, TRUE );
     473                 :                 }
     474                 : 
     475          479075 :                 pszLine += psGXF->nGType;
     476                 :             }
     477                 :         }
     478                 :     }
     479                 : 
     480                 : /* -------------------------------------------------------------------- */
     481                 : /*      Return the new offset, if requested.                            */
     482                 : /* -------------------------------------------------------------------- */
     483            1530 :     if( pnNewOffset != NULL )
     484                 :     {
     485            1530 :         *pnNewOffset = VSIFTell( psGXF->fp );
     486                 :     }
     487                 : 
     488            1530 :     return CE_None;
     489                 : }
     490                 : 
     491                 : /************************************************************************/
     492                 : /*                           GXFGetScanline()                           */
     493                 : /************************************************************************/
     494                 : 
     495                 : /**
     496                 :  * Read a scanline of raster data from GXF file.
     497                 :  *
     498                 :  * This function operates similarly to GXFGetRawScanline(), but it
     499                 :  * attempts to mirror data horizontally or vertically based on the #SENSE
     500                 :  * flag to return data in a top to bottom, and left to right organization.
     501                 :  * If the file is organized in columns (#SENSE is GXFS_UR_DOWN, GXFS_UL_DOWN,
     502                 :  * GXFS_LR_UP, or GXFS_LL_UP) then this function will fail, returning
     503                 :  * CE_Failure, and reporting a sense error.
     504                 :  *
     505                 :  * See GXFGetRawScanline() for other notes.
     506                 :  *
     507                 :  * @param hGXF the GXF file handle, as returned from GXFOpen().
     508                 :  * @param iScanline the scanline to read, zero is the top scanline.
     509                 :  * @param padfLineBuf a buffer of doubles into which the scanline pixel
     510                 :  * values are read.  This must be at least as long as a scanline.
     511                 :  *
     512                 :  * @return CE_None if access succeeds or CE_Failure if something goes wrong.
     513                 :  */
     514                 : 
     515                 : CPLErr GXFGetScanline( GXFHandle hGXF, int iScanline, double * padfLineBuf )
     516                 : 
     517               0 : {
     518               0 :     GXFInfo_t *psGXF = (GXFInfo_t *) hGXF;
     519                 :     CPLErr  nErr;
     520                 :     int   iRawScanline;
     521                 : 
     522               0 :     if( psGXF->nSense == GXFS_LL_RIGHT
     523                 :         || psGXF->nSense == GXFS_LR_LEFT )
     524                 :     {
     525               0 :         iRawScanline = psGXF->nRawYSize - iScanline - 1;
     526                 :     }
     527                 : 
     528               0 :     else if( psGXF->nSense == GXFS_UL_RIGHT
     529                 :              || psGXF->nSense == GXFS_UR_LEFT )
     530                 :     {
     531               0 :         iRawScanline = iScanline;
     532                 :     }
     533                 :     else
     534                 :     {
     535               0 :         CPLError( CE_Failure, CPLE_AppDefined,
     536                 :                   "Unable to support vertically oriented images." );
     537               0 :         return( CE_Failure );
     538                 :     }
     539                 : 
     540               0 :     nErr = GXFGetRawScanline( hGXF, iRawScanline, padfLineBuf );
     541                 : 
     542               0 :     if( nErr == CE_None
     543                 :         && (psGXF->nSense == GXFS_LR_LEFT || psGXF->nSense == GXFS_UR_LEFT) )
     544                 :     {
     545                 :         int i;
     546                 :         double  dfTemp;
     547                 :         
     548               0 :         for( i = psGXF->nRawXSize / 2 - 1; i >= 0; i-- )
     549                 :         {
     550               0 :             dfTemp = padfLineBuf[i];
     551               0 :             padfLineBuf[i] = padfLineBuf[psGXF->nRawXSize-i-1];
     552               0 :             padfLineBuf[psGXF->nRawXSize-i-1] = dfTemp;
     553                 :         }
     554                 :     }
     555                 : 
     556               0 :     return( nErr );
     557                 : }
     558                 : 
     559                 : /************************************************************************/
     560                 : /*                         GXFGetRawScanline()                          */
     561                 : /************************************************************************/
     562                 : 
     563                 : /**
     564                 :  * Read a scanline of raster data from GXF file.
     565                 :  *
     566                 :  * This function will read a row of data from the GXF file.  It is "Raw"
     567                 :  * in the sense that it doesn't attempt to account for the #SENSE flag as
     568                 :  * the GXFGetScanline() function does.  Unlike GXFGetScanline(), this function
     569                 :  * supports column organized files.
     570                 :  *
     571                 :  * Any dummy pixels are assigned the dummy value indicated by GXFGetRawInfo().
     572                 :  *
     573                 :  * @param hGXF the GXF file handle, as returned from GXFOpen().
     574                 :  * @param iScanline the scanline to read, zero is the first scanline in the
     575                 :  * file. 
     576                 :  * @param padfLineBuf a buffer of doubles into which the scanline pixel
     577                 :  * values are read.  This must be at least as long as a scanline.
     578                 :  *
     579                 :  * @return CE_None if access succeeds or CE_Failure if something goes wrong.
     580                 :  */
     581                 : 
     582                 : CPLErr GXFGetRawScanline( GXFHandle hGXF, int iScanline, double * padfLineBuf )
     583                 : 
     584            1530 : {
     585            1530 :     GXFInfo_t *psGXF = (GXFInfo_t *) hGXF;
     586                 :     CPLErr  nErr;
     587                 :     
     588                 : /* -------------------------------------------------------------------- */
     589                 : /*      Validate scanline.                                              */
     590                 : /* -------------------------------------------------------------------- */
     591            1530 :     if( iScanline < 0 || iScanline >= psGXF->nRawYSize )
     592                 :     {
     593               0 :         CPLError( CE_Failure, CPLE_IllegalArg,
     594                 :                   "GXFGetRawScanline(): Scanline `%d' does not exist.\n",
     595                 :                   iScanline );
     596               0 :         return CE_Failure;
     597                 :     }
     598                 : 
     599                 : /* -------------------------------------------------------------------- */
     600                 : /*      If we don't have the requested scanline, fetch preceeding       */
     601                 : /*      scanlines to find the pointer to this scanline.                 */
     602                 : /* -------------------------------------------------------------------- */
     603            1530 :     if( psGXF->panRawLineOffset[iScanline] == 0 )
     604                 :     {
     605                 :         int   i;
     606                 :         
     607               0 :         CPLAssert( iScanline > 0 );
     608                 : 
     609               0 :         for( i = 0; i < iScanline; i++ )
     610                 :         {
     611               0 :             if( psGXF->panRawLineOffset[i+1] == 0 )
     612                 :             {
     613               0 :                 nErr = GXFGetRawScanline( hGXF, i, padfLineBuf );
     614               0 :                 if( nErr != CE_None )
     615               0 :                     return( nErr );
     616                 :             }
     617                 :         }
     618                 :     }
     619                 : 
     620                 : /* -------------------------------------------------------------------- */
     621                 : /*      Get this scanline, and update the offset for the next line.     */
     622                 : /* -------------------------------------------------------------------- */
     623            1530 :     nErr = (CPLErr)
     624                 :         GXFReadRawScanlineFrom( psGXF, psGXF->panRawLineOffset[iScanline],
     625                 :                                 psGXF->panRawLineOffset+iScanline+1,
     626                 :                                 padfLineBuf );
     627                 : 
     628            1530 :     return nErr;
     629                 : }
     630                 : 
     631                 : /************************************************************************/
     632                 : /*                         GXFScanForZMinMax()                          */
     633                 : /*                                                                      */
     634                 : /*      The header doesn't contain the ZMin/ZMax values, but the        */
     635                 : /*      application has requested it ... scan the entire image for      */
     636                 : /*      it.                                                             */
     637                 : /************************************************************************/
     638                 : 
     639                 : static void GXFScanForZMinMax( GXFHandle hGXF )
     640                 : 
     641               0 : {
     642               0 :     GXFInfo_t *psGXF = (GXFInfo_t *) hGXF;
     643                 :     int   iLine, iPixel;
     644                 :     double  *padfScanline;
     645                 :     
     646                 : 
     647               0 :     padfScanline = (double *) VSICalloc(sizeof(double),psGXF->nRawXSize);
     648               0 :     if( padfScanline == NULL )
     649               0 :         return;
     650                 : 
     651               0 :     psGXF->dfZMinimum = 1e50;
     652               0 :     psGXF->dfZMaximum = -1e50;
     653                 : 
     654               0 :     for( iLine = 0; iLine < psGXF->nRawYSize; iLine++ )
     655                 :     {
     656               0 :         if( GXFGetRawScanline( hGXF, iLine, padfScanline ) != CE_None )
     657               0 :             break;
     658                 : 
     659               0 :         for( iPixel = 0; iPixel < psGXF->nRawXSize; iPixel++ )
     660                 :         {
     661               0 :             if( padfScanline[iPixel] != psGXF->dfSetDummyTo )
     662                 :             {
     663               0 :                 psGXF->dfZMinimum =
     664                 :                     MIN(psGXF->dfZMinimum,padfScanline[iPixel]);
     665               0 :                 psGXF->dfZMaximum =
     666                 :                     MAX(psGXF->dfZMaximum,padfScanline[iPixel]);
     667                 :             }
     668                 :         }
     669                 :     }
     670                 : 
     671               0 :     VSIFree( padfScanline );
     672                 : 
     673                 : /* -------------------------------------------------------------------- */
     674                 : /*      Did we get any real data points?                                */
     675                 : /* -------------------------------------------------------------------- */
     676               0 :     if( psGXF->dfZMinimum > psGXF->dfZMaximum )
     677                 :     {
     678               0 :         psGXF->dfZMinimum = 0.0;
     679               0 :         psGXF->dfZMaximum = 0.0;
     680                 :     }
     681                 : }
     682                 : 
     683                 : /************************************************************************/
     684                 : /*                             GXFGetRawInfo()                          */
     685                 : /************************************************************************/
     686                 : 
     687                 : /**
     688                 :  * Fetch header information about a GXF file.
     689                 :  *
     690                 :  * Note that the X and Y sizes are of the raw raster and don't take into
     691                 :  * account the #SENSE flag.  If the file is column oriented (rows in the
     692                 :  * files are actually columns in the raster) these values would need to be
     693                 :  * transposed for the actual raster.
     694                 :  *
     695                 :  * The legal pnSense values are:
     696                 :  * <ul>
     697                 :  * <li> GXFS_LL_UP(-1): lower left origin, scanning up.
     698                 :  * <li> GXFS_LL_RIGHT(1): lower left origin, scanning right.
     699                 :  * <li> GXFS_UL_RIGHT(-2): upper left origin, scanning right.
     700                 :  * <li> GXFS_UL_DOWN(2): upper left origin, scanning down.
     701                 :  * <li> GXFS_UR_DOWN(-3): upper right origin, scanning down.
     702                 :  * <li> GXFS_UR_LEFT(3): upper right origin, scanning left.
     703                 :  * <li> GXFS_LR_LEFT(-4): lower right origin, scanning left.
     704                 :  * <li> GXFS_LR_UP(4): lower right origin, scanning up.
     705                 :  * </ul>
     706                 :  *
     707                 :  * Note that the GXFGetScanline() function attempts to provide a GXFS_UL_RIGHT
     708                 :  * view onto files, but doesn't handle the *_DOWN and *_UP oriented files.
     709                 :  *
     710                 :  * The Z min and max values may not occur in the GXF header.  If they are
     711                 :  * requested, and aren't available in the header the entire file is scanned
     712                 :  * in order to establish them.  This can be expensive.
     713                 :  *
     714                 :  * If no #DUMMY value was specified in the file, a default of -1e12 is used.
     715                 :  * 
     716                 :  * @param hGXF handle to GXF file returned by GXFOpen().
     717                 :  * @param pnXSize int to be set with the width of the raw raster.  May be NULL.
     718                 :  * @param pnYSize int to be set with the height of the raw raster. May be NULL.
     719                 :  * @param pnSense int to set with #SENSE flag, may be NULL.
     720                 :  * @param pdfZMin double to set with minimum raster value, may be NULL.
     721                 :  * @param pdfZMax double to set with minimum raster value, may be NULL.
     722                 :  * @param pdfDummy double to set with dummy (nodata / invalid data) pixel
     723                 :  * value.
     724                 :  */ 
     725                 : 
     726                 : CPLErr GXFGetRawInfo( GXFHandle hGXF, int *pnXSize, int *pnYSize,
     727                 :                       int * pnSense, double * pdfZMin, double * pdfZMax,
     728                 :                       double * pdfDummy )
     729                 : 
     730               7 : {
     731               7 :     GXFInfo_t *psGXF = (GXFInfo_t *) hGXF;
     732                 : 
     733               7 :     if( pnXSize != NULL )
     734               7 :         *pnXSize = psGXF->nRawXSize;
     735                 : 
     736               7 :     if( pnYSize != NULL )
     737               7 :         *pnYSize = psGXF->nRawYSize;
     738                 : 
     739               7 :     if( pnSense != NULL )
     740               0 :         *pnSense = psGXF->nSense;
     741                 : 
     742               7 :     if( (pdfZMin != NULL || pdfZMax != NULL)
     743                 :         && psGXF->dfZMinimum == 0.0 && psGXF->dfZMaximum == 0.0 )
     744                 :     {
     745               0 :         GXFScanForZMinMax( hGXF );
     746                 :     }
     747                 :     
     748               7 :     if( pdfZMin != NULL )
     749               0 :         *pdfZMin = psGXF->dfZMinimum;
     750                 : 
     751               7 :     if( pdfZMax != NULL )
     752               0 :         *pdfZMax = psGXF->dfZMaximum;
     753                 : 
     754               7 :     if( pdfDummy != NULL )
     755               7 :         *pdfDummy = psGXF->dfSetDummyTo;
     756                 : 
     757               7 :     return( CE_None );
     758                 : }
     759                 : 
     760                 : /************************************************************************/
     761                 : /*                        GXFGetMapProjection()                         */
     762                 : /************************************************************************/
     763                 : 
     764                 : /**
     765                 :  * Return the lines related to the map projection.  It is up to   
     766                 :  * the caller to parse them and interprete.  The return result    
     767                 :  * will be NULL if no #MAP_PROJECTION line was found in the header.
     768                 :  * 
     769                 :  * @param hGXF the GXF file handle.
     770                 :  *
     771                 :  * @return a NULL terminated array of string pointers containing the
     772                 :  * projection, or NULL.  The strings remained owned by the GXF API, and
     773                 :  * should not be modified or freed by the caller.  
     774                 :  */
     775                 : 
     776                 : char **GXFGetMapProjection( GXFHandle hGXF )
     777                 : 
     778               0 : {
     779               0 :     return( ((GXFInfo_t *) hGXF)->papszMapProjection );
     780                 : }
     781                 : 
     782                 : /************************************************************************/
     783                 : /*                      GXFGetMapDatumTransform()                       */
     784                 : /************************************************************************/
     785                 : 
     786                 : /**
     787                 :  * Return the lines related to the datum transformation.  It is up to   
     788                 :  * the caller to parse them and interpret.  The return result    
     789                 :  * will be NULL if no #MAP_DATUM_TRANSFORM line was found in the header.
     790                 :  * 
     791                 :  * @param hGXF the GXF file handle.
     792                 :  *
     793                 :  * @return a NULL terminated array of string pointers containing the
     794                 :  * datum, or NULL.  The strings remained owned by the GXF API, and
     795                 :  * should not be modified or freed by the caller.  
     796                 :  */
     797                 : 
     798                 : char **GXFGetMapDatumTransform( GXFHandle hGXF )
     799                 : 
     800               0 : {
     801               0 :     return( ((GXFInfo_t *) hGXF)->papszMapDatumTransform );
     802                 : }
     803                 : 
     804                 : /************************************************************************/
     805                 : /*                         GXFGetRawPosition()                          */
     806                 : /************************************************************************/
     807                 : 
     808                 : /**
     809                 :  * Get the raw grid positioning information.
     810                 :  *
     811                 :  * Note that these coordinates refer to the raw grid, and are in the units
     812                 :  * specified by the #UNITS field.  See GXFGetPosition() for a similar
     813                 :  * function that takes into account the #SENSE values similarly to
     814                 :  * GXFGetScanline().
     815                 :  *
     816                 :  * Note that the pixel values are considered to be point values in GXF,
     817                 :  * and thus the origin is for the first point.  If you consider the pixels
     818                 :  * to be areas, then the origin is for the center of the origin pixel, not
     819                 :  * the outer corner.
     820                 :  *
     821                 :  * @param hGXF the GXF file handle.
     822                 :  * @param pdfXOrigin X position of the origin in the base coordinate system.
     823                 :  * @param pdfYOrigin Y position of the origin in the base coordinate system.
     824                 :  * @param pdfXPixelSize X pixel size in base coordinates.
     825                 :  * @param pdfYPixelSize Y pixel size in base coordinates.
     826                 :  * @param pdfRotation rotation in degrees counter-clockwise from the
     827                 :  * base coordinate system.
     828                 :  *
     829                 :  * @return Returns CE_None if successful, or CE_Failure if no posiitioning
     830                 :  * information was found in the file.
     831                 :  */
     832                 :  
     833                 : 
     834                 : CPLErr GXFGetRawPosition( GXFHandle hGXF,
     835                 :                           double * pdfXOrigin, double * pdfYOrigin,
     836                 :                           double * pdfXPixelSize, double * pdfYPixelSize,
     837                 :                           double * pdfRotation )
     838                 : 
     839               0 : {
     840               0 :     GXFInfo_t *psGXF = (GXFInfo_t *) hGXF;
     841                 :     
     842               0 :     if( pdfXOrigin != NULL )
     843               0 :         *pdfXOrigin = psGXF->dfXOrigin;
     844               0 :     if( pdfYOrigin != NULL )
     845               0 :         *pdfYOrigin = psGXF->dfYOrigin;
     846               0 :     if( pdfXPixelSize != NULL )
     847               0 :         *pdfXPixelSize = psGXF->dfXPixelSize;
     848               0 :     if( pdfYPixelSize != NULL )
     849               0 :         *pdfYPixelSize = psGXF->dfYPixelSize;
     850               0 :     if( pdfRotation != NULL )
     851               0 :         *pdfRotation = psGXF->dfRotation;
     852                 : 
     853               0 :     if( psGXF->dfXOrigin == 0.0 && psGXF->dfYOrigin == 0.0
     854                 :         && psGXF->dfXPixelSize == 0.0 && psGXF->dfYPixelSize == 0.0 )
     855               0 :         return( CE_Failure );
     856                 :     else
     857               0 :         return( CE_None );
     858                 : }
     859                 : 
     860                 : 
     861                 : /************************************************************************/
     862                 : /*                           GXFGetPosition()                           */
     863                 : /************************************************************************/
     864                 : 
     865                 : /**
     866                 :  * Get the grid positioning information.
     867                 :  *
     868                 :  * Note that these coordinates refer to the grid positioning after taking
     869                 :  * into account the #SENSE flag (as is done by the GXFGetScanline()) function.
     870                 :  *
     871                 :  * Note that the pixel values are considered to be point values in GXF,
     872                 :  * and thus the origin is for the first point.  If you consider the pixels
     873                 :  * to be areas, then the origin is for the center of the origin pixel, not
     874                 :  * the outer corner.
     875                 :  *
     876                 :  * This function does not support vertically oriented images, nor does it
     877                 :  * properly transform rotation for images with a SENSE other than
     878                 :  * GXFS_UL_RIGHT.
     879                 :  *
     880                 :  * @param hGXF the GXF file handle.
     881                 :  * @param pdfXOrigin X position of the origin in the base coordinate system.
     882                 :  * @param pdfYOrigin Y position of the origin in the base coordinate system.
     883                 :  * @param pdfXPixelSize X pixel size in base coordinates.
     884                 :  * @param pdfYPixelSize Y pixel size in base coordinates.
     885                 :  * @param pdfRotation rotation in degrees counter-clockwise from the
     886                 :  * base coordinate system.
     887                 :  *
     888                 :  * @return Returns CE_None if successful, or CE_Failure if no posiitioning
     889                 :  * information was found in the file.
     890                 :  */
     891                 :  
     892                 : 
     893                 : CPLErr GXFGetPosition( GXFHandle hGXF,
     894                 :                        double * pdfXOrigin, double * pdfYOrigin,
     895                 :                        double * pdfXPixelSize, double * pdfYPixelSize,
     896                 :                        double * pdfRotation )
     897                 : 
     898               0 : {
     899               0 :     GXFInfo_t *psGXF = (GXFInfo_t *) hGXF;
     900                 :     double  dfCXOrigin, dfCYOrigin, dfCXPixelSize, dfCYPixelSize;
     901                 : 
     902               0 :     switch( psGXF->nSense )
     903                 :     {
     904                 :       case GXFS_UL_RIGHT:
     905               0 :         dfCXOrigin = psGXF->dfXOrigin;
     906               0 :         dfCYOrigin = psGXF->dfYOrigin;
     907               0 :         dfCXPixelSize = psGXF->dfXPixelSize;
     908               0 :         dfCYPixelSize = psGXF->dfYPixelSize;
     909               0 :         break;
     910                 :         
     911                 :       case GXFS_UR_LEFT:
     912               0 :         dfCXOrigin = psGXF->dfXOrigin
     913                 :                    - (psGXF->nRawXSize-1) * psGXF->dfXPixelSize;
     914               0 :         dfCYOrigin = psGXF->dfYOrigin;
     915               0 :         dfCXPixelSize = psGXF->dfXPixelSize;
     916               0 :         dfCYPixelSize = psGXF->dfYPixelSize;
     917               0 :         break;
     918                 :         
     919                 :       case GXFS_LL_RIGHT:
     920               0 :         dfCXOrigin = psGXF->dfXOrigin;
     921               0 :         dfCYOrigin = psGXF->dfYOrigin
     922                 :                      + (psGXF->nRawYSize-1) * psGXF->dfYPixelSize;
     923               0 :         dfCXPixelSize = psGXF->dfXPixelSize;
     924               0 :         dfCYPixelSize = psGXF->dfYPixelSize;
     925               0 :         break;
     926                 :         
     927                 :       case GXFS_LR_LEFT:
     928               0 :         dfCXOrigin = psGXF->dfXOrigin
     929                 :                    - (psGXF->nRawXSize-1) * psGXF->dfXPixelSize;
     930               0 :         dfCYOrigin = psGXF->dfYOrigin
     931                 :                      + (psGXF->nRawYSize-1) * psGXF->dfYPixelSize;
     932               0 :         dfCXPixelSize = psGXF->dfXPixelSize;
     933               0 :         dfCYPixelSize = psGXF->dfYPixelSize;
     934               0 :         break;
     935                 : 
     936                 :       default:
     937               0 :         CPLError( CE_Failure, CPLE_AppDefined,
     938                 :            "GXFGetPosition() doesn't support vertically organized images." );
     939               0 :         return CE_Failure;
     940                 :     }
     941                 : 
     942               0 :     if( pdfXOrigin != NULL )
     943               0 :         *pdfXOrigin = dfCXOrigin;
     944               0 :     if( pdfYOrigin != NULL )
     945               0 :         *pdfYOrigin = dfCYOrigin;
     946               0 :     if( pdfXPixelSize != NULL )
     947               0 :         *pdfXPixelSize = dfCXPixelSize;
     948               0 :     if( pdfYPixelSize != NULL )
     949               0 :         *pdfYPixelSize = dfCYPixelSize;
     950               0 :     if( pdfRotation != NULL )
     951               0 :         *pdfRotation = psGXF->dfRotation;
     952                 : 
     953               0 :     if( psGXF->dfXOrigin == 0.0 && psGXF->dfYOrigin == 0.0
     954                 :         && psGXF->dfXPixelSize == 0.0 && psGXF->dfYPixelSize == 0.0 )
     955               0 :         return( CE_Failure );
     956                 :     else
     957               0 :         return( CE_None );
     958                 : }
     959                 : 
     960                 : 

Generated by: LTP GCOV extension version 1.5