LCOV - code coverage report
Current view: directory - frmts/gxf - gxfopen.c (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 299 170 56.9 %
Date: 2010-01-09 Functions: 13 7 53.8 %

       1                 : /******************************************************************************
       2                 :  * $Id: gxfopen.c 16865 2009-04-27 12:49:49Z chaitanya $
       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 16865 2009-04-27 12:49:49Z chaitanya $");
      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              96 : static char **GXFReadHeaderValue( FILE * fp, char * pszHTitle )
      48                 : 
      49                 : {
      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               7 : GXFHandle GXFOpen( const char * pszFilename )
     143                 : 
     144                 : {
     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               7 :         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               7 : void GXFClose( GXFHandle hGXF )
     335                 : 
     336                 : {
     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                 : 
     345               7 :     VSIFClose( psGXF->fp );
     346                 : 
     347               7 :     CPLReadLine( NULL );
     348                 : 
     349               7 :     CPLFree( psGXF );
     350               7 : }
     351                 : 
     352                 : /************************************************************************/
     353                 : /*                           GXFParseBase90()                           */
     354                 : /*                                                                      */
     355                 : /*      Parse a base 90 number ... exceptions (repeat, and dummy)       */
     356                 : /*      values have to be recognised outside this function.             */
     357                 : /************************************************************************/
     358                 : 
     359          477843 : double GXFParseBase90( GXFInfo_t * psGXF, const char * pszText,
     360                 :                        int bScale )
     361                 : 
     362                 : {
     363          477843 :     int   i = 0, nValue = 0;
     364                 : 
     365         2867058 :     while( i < psGXF->nGType )
     366                 :     {
     367         1911372 :         nValue = nValue*90 + (pszText[i] - 37);
     368         1911372 :         i++;
     369                 :     }
     370                 : 
     371          477843 :     if( bScale ) 
     372          476828 :         return( (nValue * psGXF->dfTransformScale) + psGXF->dfTransformOffset);
     373                 :     else
     374            1015 :         return( nValue );
     375                 : }
     376                 : 
     377                 : 
     378                 : /************************************************************************/
     379                 : /*                       GXFReadRawScanlineFrom()                       */
     380                 : /************************************************************************/
     381                 : 
     382            1530 : static int GXFReadRawScanlineFrom( GXFInfo_t * psGXF, long iOffset,
     383                 :                                    long * pnNewOffset, double * padfLineBuf )
     384                 : 
     385                 : {
     386                 :     const char  *pszLine;
     387            1530 :     int   nValuesRead = 0, nValuesSought = psGXF->nRawXSize;
     388                 :     
     389            1530 :     VSIFSeek( psGXF->fp, iOffset, SEEK_SET );
     390                 : 
     391           41554 :     while( nValuesRead < nValuesSought )
     392                 :     {
     393           38494 :         pszLine = CPLReadLine( psGXF->fp );
     394           38494 :         if( pszLine == NULL )
     395               0 :             break;
     396                 : 
     397                 : /* -------------------------------------------------------------------- */
     398                 : /*      Uncompressed case.                                              */
     399                 : /* -------------------------------------------------------------------- */
     400           38494 :         if( psGXF->nGType == 0 )
     401                 :         {
     402                 :             /* we could just tokenize the line, but that's pretty expensive.
     403                 :                Instead I will parse on white space ``by hand''. */
     404          138216 :             while( *pszLine != '\0' && nValuesRead < nValuesSought )
     405                 :             {
     406                 :                 int   i;
     407                 :                 
     408                 :                 /* skip leading white space */
     409          110130 :                 for( ; isspace((unsigned char)*pszLine); pszLine++ ) {}
     410                 : 
     411                 :                 /* Skip the data value (non white space) */
     412          110130 :                 for( i = 0; pszLine[i] != '\0' && !isspace((unsigned char)pszLine[i]); i++) {}
     413                 : 
     414          110130 :                 if( strncmp(pszLine,psGXF->szDummy,i) == 0 )
     415                 :                 {
     416           17731 :                     padfLineBuf[nValuesRead++] = psGXF->dfSetDummyTo;
     417                 :                 }
     418                 :                 else
     419                 :                 {
     420           92399 :                     padfLineBuf[nValuesRead++] = atof(pszLine);
     421                 :                 }
     422                 : 
     423                 :                 /* skip further whitespace */
     424          110130 :                 for( pszLine += i; isspace((unsigned char)*pszLine); pszLine++ ) {}
     425                 :             }
     426                 :         }
     427                 : 
     428                 : /* -------------------------------------------------------------------- */
     429                 : /*      Compressed case.                                                */
     430                 : /* -------------------------------------------------------------------- */
     431                 :         else
     432                 :         {
     433          527977 :             while( *pszLine != '\0' && nValuesRead < nValuesSought )
     434                 :             {
     435          479075 :                 if( pszLine[0] == '!' )
     436                 :                 {
     437            1887 :                     padfLineBuf[nValuesRead++] = psGXF->dfSetDummyTo;
     438                 :                 }
     439          477188 :                 else if( pszLine[0] == '"' )
     440                 :                 {
     441                 :                     int   nCount, i;
     442                 :                     double  dfValue;
     443                 : 
     444            1015 :                     pszLine += psGXF->nGType;
     445            1015 :                     if( (int) strlen(pszLine) < psGXF->nGType )
     446              22 :                         pszLine = CPLReadLine( psGXF->fp );
     447                 :                     
     448            1015 :                     nCount = (int) GXFParseBase90( psGXF, pszLine, FALSE);
     449            1015 :                     pszLine += psGXF->nGType;
     450                 :                     
     451            1015 :                     if( (int) strlen(pszLine) < psGXF->nGType )
     452              34 :                         pszLine = CPLReadLine( psGXF->fp );
     453                 :                     
     454            1015 :                     if( *pszLine == '!' )
     455             360 :                         dfValue = psGXF->dfSetDummyTo;
     456                 :                     else
     457             655 :                         dfValue = GXFParseBase90( psGXF, pszLine, TRUE );
     458                 : 
     459            1015 :                     if( nValuesRead + nCount > nValuesSought )
     460                 :                     {
     461               0 :                         CPLError(CE_Failure, CPLE_AppDefined, "Wrong count value");
     462               0 :                         return CE_Failure;
     463                 :                     }
     464                 :                     
     465           25212 :                     for( i=0; i < nCount && nValuesRead < nValuesSought; i++ )
     466           24197 :                         padfLineBuf[nValuesRead++] = dfValue;
     467                 :                 }
     468                 :                 else
     469                 :                 {
     470          952346 :                     padfLineBuf[nValuesRead++] =
     471          476173 :                         GXFParseBase90( psGXF, pszLine, TRUE );
     472                 :                 }
     473                 : 
     474          479075 :                 pszLine += psGXF->nGType;
     475                 :             }
     476                 :         }
     477                 :     }
     478                 : 
     479                 : /* -------------------------------------------------------------------- */
     480                 : /*      Return the new offset, if requested.                            */
     481                 : /* -------------------------------------------------------------------- */
     482            1530 :     if( pnNewOffset != NULL )
     483                 :     {
     484            1530 :         *pnNewOffset = VSIFTell( psGXF->fp );
     485                 :     }
     486                 : 
     487            1530 :     return CE_None;
     488                 : }
     489                 : 
     490                 : /************************************************************************/
     491                 : /*                           GXFGetScanline()                           */
     492                 : /************************************************************************/
     493                 : 
     494                 : /**
     495                 :  * Read a scanline of raster data from GXF file.
     496                 :  *
     497                 :  * This function operates similarly to GXFGetRawScanline(), but it
     498                 :  * attempts to mirror data horizontally or vertically based on the #SENSE
     499                 :  * flag to return data in a top to bottom, and left to right organization.
     500                 :  * If the file is organized in columns (#SENSE is GXFS_UR_DOWN, GXFS_UL_DOWN,
     501                 :  * GXFS_LR_UP, or GXFS_LL_UP) then this function will fail, returning
     502                 :  * CE_Failure, and reporting a sense error.
     503                 :  *
     504                 :  * See GXFGetRawScanline() for other notes.
     505                 :  *
     506                 :  * @param hGXF the GXF file handle, as returned from GXFOpen().
     507                 :  * @param iScanline the scanline to read, zero is the top scanline.
     508                 :  * @param padfLineBuf a buffer of doubles into which the scanline pixel
     509                 :  * values are read.  This must be at least as long as a scanline.
     510                 :  *
     511                 :  * @return CE_None if access succeeds or CE_Failure if something goes wrong.
     512                 :  */
     513                 : 
     514               0 : CPLErr GXFGetScanline( GXFHandle hGXF, int iScanline, double * padfLineBuf )
     515                 : 
     516                 : {
     517               0 :     GXFInfo_t *psGXF = (GXFInfo_t *) hGXF;
     518                 :     CPLErr  nErr;
     519                 :     int   iRawScanline;
     520                 : 
     521               0 :     if( psGXF->nSense == GXFS_LL_RIGHT
     522               0 :         || psGXF->nSense == GXFS_LR_LEFT )
     523                 :     {
     524               0 :         iRawScanline = psGXF->nRawYSize - iScanline - 1;
     525                 :     }
     526                 : 
     527               0 :     else if( psGXF->nSense == GXFS_UL_RIGHT
     528               0 :              || psGXF->nSense == GXFS_UR_LEFT )
     529                 :     {
     530               0 :         iRawScanline = iScanline;
     531                 :     }
     532                 :     else
     533                 :     {
     534               0 :         CPLError( CE_Failure, CPLE_AppDefined,
     535                 :                   "Unable to support vertically oriented images." );
     536               0 :         return( CE_Failure );
     537                 :     }
     538                 : 
     539               0 :     nErr = GXFGetRawScanline( hGXF, iRawScanline, padfLineBuf );
     540                 : 
     541               0 :     if( nErr == CE_None
     542               0 :         && (psGXF->nSense == GXFS_LR_LEFT || psGXF->nSense == GXFS_UR_LEFT) )
     543                 :     {
     544                 :         int i;
     545                 :         double  dfTemp;
     546                 :         
     547               0 :         for( i = psGXF->nRawXSize / 2 - 1; i >= 0; i-- )
     548                 :         {
     549               0 :             dfTemp = padfLineBuf[i];
     550               0 :             padfLineBuf[i] = padfLineBuf[psGXF->nRawXSize-i-1];
     551               0 :             padfLineBuf[psGXF->nRawXSize-i-1] = dfTemp;
     552                 :         }
     553                 :     }
     554                 : 
     555               0 :     return( nErr );
     556                 : }
     557                 : 
     558                 : /************************************************************************/
     559                 : /*                         GXFGetRawScanline()                          */
     560                 : /************************************************************************/
     561                 : 
     562                 : /**
     563                 :  * Read a scanline of raster data from GXF file.
     564                 :  *
     565                 :  * This function will read a row of data from the GXF file.  It is "Raw"
     566                 :  * in the sense that it doesn't attempt to account for the #SENSE flag as
     567                 :  * the GXFGetScanline() function does.  Unlike GXFGetScanline(), this function
     568                 :  * supports column organized files.
     569                 :  *
     570                 :  * Any dummy pixels are assigned the dummy value indicated by GXFGetRawInfo().
     571                 :  *
     572                 :  * @param hGXF the GXF file handle, as returned from GXFOpen().
     573                 :  * @param iScanline the scanline to read, zero is the first scanline in the
     574                 :  * file. 
     575                 :  * @param padfLineBuf a buffer of doubles into which the scanline pixel
     576                 :  * values are read.  This must be at least as long as a scanline.
     577                 :  *
     578                 :  * @return CE_None if access succeeds or CE_Failure if something goes wrong.
     579                 :  */
     580                 : 
     581            1530 : CPLErr GXFGetRawScanline( GXFHandle hGXF, int iScanline, double * padfLineBuf )
     582                 : 
     583                 : {
     584            1530 :     GXFInfo_t *psGXF = (GXFInfo_t *) hGXF;
     585                 :     CPLErr  nErr;
     586                 :     
     587                 : /* -------------------------------------------------------------------- */
     588                 : /*      Validate scanline.                                              */
     589                 : /* -------------------------------------------------------------------- */
     590            1530 :     if( iScanline < 0 || iScanline >= psGXF->nRawYSize )
     591                 :     {
     592               0 :         CPLError( CE_Failure, CPLE_IllegalArg,
     593                 :                   "GXFGetRawScanline(): Scanline `%d' does not exist.\n",
     594                 :                   iScanline );
     595               0 :         return CE_Failure;
     596                 :     }
     597                 : 
     598                 : /* -------------------------------------------------------------------- */
     599                 : /*      If we don't have the requested scanline, fetch preceeding       */
     600                 : /*      scanlines to find the pointer to this scanline.                 */
     601                 : /* -------------------------------------------------------------------- */
     602            1530 :     if( psGXF->panRawLineOffset[iScanline] == 0 )
     603                 :     {
     604                 :         int   i;
     605                 :         
     606                 :         CPLAssert( iScanline > 0 );
     607                 : 
     608               0 :         for( i = 0; i < iScanline; i++ )
     609                 :         {
     610               0 :             if( psGXF->panRawLineOffset[i+1] == 0 )
     611                 :             {
     612               0 :                 nErr = GXFGetRawScanline( hGXF, i, padfLineBuf );
     613               0 :                 if( nErr != CE_None )
     614               0 :                     return( nErr );
     615                 :             }
     616                 :         }
     617                 :     }
     618                 : 
     619                 : /* -------------------------------------------------------------------- */
     620                 : /*      Get this scanline, and update the offset for the next line.     */
     621                 : /* -------------------------------------------------------------------- */
     622            3060 :     nErr = (CPLErr)
     623            1530 :         GXFReadRawScanlineFrom( psGXF, psGXF->panRawLineOffset[iScanline],
     624                 :                                 psGXF->panRawLineOffset+iScanline+1,
     625                 :                                 padfLineBuf );
     626                 : 
     627            1530 :     return nErr;
     628                 : }
     629                 : 
     630                 : /************************************************************************/
     631                 : /*                         GXFScanForZMinMax()                          */
     632                 : /*                                                                      */
     633                 : /*      The header doesn't contain the ZMin/ZMax values, but the        */
     634                 : /*      application has requested it ... scan the entire image for      */
     635                 : /*      it.                                                             */
     636                 : /************************************************************************/
     637                 : 
     638               0 : static void GXFScanForZMinMax( GXFHandle hGXF )
     639                 : 
     640                 : {
     641               0 :     GXFInfo_t *psGXF = (GXFInfo_t *) hGXF;
     642                 :     int   iLine, iPixel;
     643                 :     double  *padfScanline;
     644                 :     
     645                 : 
     646               0 :     padfScanline = (double *) VSICalloc(sizeof(double),psGXF->nRawXSize);
     647               0 :     if( padfScanline == NULL )
     648               0 :         return;
     649                 : 
     650               0 :     psGXF->dfZMinimum = 1e50;
     651               0 :     psGXF->dfZMaximum = -1e50;
     652                 : 
     653               0 :     for( iLine = 0; iLine < psGXF->nRawYSize; iLine++ )
     654                 :     {
     655               0 :         if( GXFGetRawScanline( hGXF, iLine, padfScanline ) != CE_None )
     656               0 :             break;
     657                 : 
     658               0 :         for( iPixel = 0; iPixel < psGXF->nRawXSize; iPixel++ )
     659                 :         {
     660               0 :             if( padfScanline[iPixel] != psGXF->dfSetDummyTo )
     661                 :             {
     662               0 :                 psGXF->dfZMinimum =
     663               0 :                     MIN(psGXF->dfZMinimum,padfScanline[iPixel]);
     664               0 :                 psGXF->dfZMaximum =
     665               0 :                     MAX(psGXF->dfZMaximum,padfScanline[iPixel]);
     666                 :             }
     667                 :         }
     668                 :     }
     669                 : 
     670               0 :     VSIFree( padfScanline );
     671                 : 
     672                 : /* -------------------------------------------------------------------- */
     673                 : /*      Did we get any real data points?                                */
     674                 : /* -------------------------------------------------------------------- */
     675               0 :     if( psGXF->dfZMinimum > psGXF->dfZMaximum )
     676                 :     {
     677               0 :         psGXF->dfZMinimum = 0.0;
     678               0 :         psGXF->dfZMaximum = 0.0;
     679                 :     }
     680                 : }
     681                 : 
     682                 : /************************************************************************/
     683                 : /*                             GXFGetRawInfo()                          */
     684                 : /************************************************************************/
     685                 : 
     686                 : /**
     687                 :  * Fetch header information about a GXF file.
     688                 :  *
     689                 :  * Note that the X and Y sizes are of the raw raster and don't take into
     690                 :  * account the #SENSE flag.  If the file is column oriented (rows in the
     691                 :  * files are actually columns in the raster) these values would need to be
     692                 :  * transposed for the actual raster.
     693                 :  *
     694                 :  * The legal pnSense values are:
     695                 :  * <ul>
     696                 :  * <li> GXFS_LL_UP(-1): lower left origin, scanning up.
     697                 :  * <li> GXFS_LL_RIGHT(1): lower left origin, scanning right.
     698                 :  * <li> GXFS_UL_RIGHT(-2): upper left origin, scanning right.
     699                 :  * <li> GXFS_UL_DOWN(2): upper left origin, scanning down.
     700                 :  * <li> GXFS_UR_DOWN(-3): upper right origin, scanning down.
     701                 :  * <li> GXFS_UR_LEFT(3): upper right origin, scanning left.
     702                 :  * <li> GXFS_LR_LEFT(-4): lower right origin, scanning left.
     703                 :  * <li> GXFS_LR_UP(4): lower right origin, scanning up.
     704                 :  * </ul>
     705                 :  *
     706                 :  * Note that the GXFGetScanline() function attempts to provide a GXFS_UL_RIGHT
     707                 :  * view onto files, but doesn't handle the *_DOWN and *_UP oriented files.
     708                 :  *
     709                 :  * The Z min and max values may not occur in the GXF header.  If they are
     710                 :  * requested, and aren't available in the header the entire file is scanned
     711                 :  * in order to establish them.  This can be expensive.
     712                 :  *
     713                 :  * If no #DUMMY value was specified in the file, a default of -1e12 is used.
     714                 :  * 
     715                 :  * @param hGXF handle to GXF file returned by GXFOpen().
     716                 :  * @param pnXSize int to be set with the width of the raw raster.  May be NULL.
     717                 :  * @param pnYSize int to be set with the height of the raw raster. May be NULL.
     718                 :  * @param pnSense int to set with #SENSE flag, may be NULL.
     719                 :  * @param pdfZMin double to set with minimum raster value, may be NULL.
     720                 :  * @param pdfZMax double to set with minimum raster value, may be NULL.
     721                 :  * @param pdfDummy double to set with dummy (nodata / invalid data) pixel
     722                 :  * value.
     723                 :  */ 
     724                 : 
     725               7 : CPLErr GXFGetRawInfo( GXFHandle hGXF, int *pnXSize, int *pnYSize,
     726                 :                       int * pnSense, double * pdfZMin, double * pdfZMax,
     727                 :                       double * pdfDummy )
     728                 : 
     729                 : {
     730               7 :     GXFInfo_t *psGXF = (GXFInfo_t *) hGXF;
     731                 : 
     732               7 :     if( pnXSize != NULL )
     733               7 :         *pnXSize = psGXF->nRawXSize;
     734                 : 
     735               7 :     if( pnYSize != NULL )
     736               7 :         *pnYSize = psGXF->nRawYSize;
     737                 : 
     738               7 :     if( pnSense != NULL )
     739               0 :         *pnSense = psGXF->nSense;
     740                 : 
     741               7 :     if( (pdfZMin != NULL || pdfZMax != NULL)
     742               0 :         && psGXF->dfZMinimum == 0.0 && psGXF->dfZMaximum == 0.0 )
     743                 :     {
     744               0 :         GXFScanForZMinMax( hGXF );
     745                 :     }
     746                 :     
     747               7 :     if( pdfZMin != NULL )
     748               0 :         *pdfZMin = psGXF->dfZMinimum;
     749                 : 
     750               7 :     if( pdfZMax != NULL )
     751               0 :         *pdfZMax = psGXF->dfZMaximum;
     752                 : 
     753               7 :     if( pdfDummy != NULL )
     754               7 :         *pdfDummy = psGXF->dfSetDummyTo;
     755                 : 
     756               7 :     return( CE_None );
     757                 : }
     758                 : 
     759                 : /************************************************************************/
     760                 : /*                        GXFGetMapProjection()                         */
     761                 : /************************************************************************/
     762                 : 
     763                 : /**
     764                 :  * Return the lines related to the map projection.  It is up to   
     765                 :  * the caller to parse them and interprete.  The return result    
     766                 :  * will be NULL if no #MAP_PROJECTION line was found in the header.
     767                 :  * 
     768                 :  * @param hGXF the GXF file handle.
     769                 :  *
     770                 :  * @return a NULL terminated array of string pointers containing the
     771                 :  * projection, or NULL.  The strings remained owned by the GXF API, and
     772                 :  * should not be modified or freed by the caller.  
     773                 :  */
     774                 : 
     775               0 : char **GXFGetMapProjection( GXFHandle hGXF )
     776                 : 
     777                 : {
     778               0 :     return( ((GXFInfo_t *) hGXF)->papszMapProjection );
     779                 : }
     780                 : 
     781                 : /************************************************************************/
     782                 : /*                      GXFGetMapDatumTransform()                       */
     783                 : /************************************************************************/
     784                 : 
     785                 : /**
     786                 :  * Return the lines related to the datum transformation.  It is up to   
     787                 :  * the caller to parse them and interpret.  The return result    
     788                 :  * will be NULL if no #MAP_DATUM_TRANSFORM line was found in the header.
     789                 :  * 
     790                 :  * @param hGXF the GXF file handle.
     791                 :  *
     792                 :  * @return a NULL terminated array of string pointers containing the
     793                 :  * datum, or NULL.  The strings remained owned by the GXF API, and
     794                 :  * should not be modified or freed by the caller.  
     795                 :  */
     796                 : 
     797               0 : char **GXFGetMapDatumTransform( GXFHandle hGXF )
     798                 : 
     799                 : {
     800               0 :     return( ((GXFInfo_t *) hGXF)->papszMapDatumTransform );
     801                 : }
     802                 : 
     803                 : /************************************************************************/
     804                 : /*                         GXFGetRawPosition()                          */
     805                 : /************************************************************************/
     806                 : 
     807                 : /**
     808                 :  * Get the raw grid positioning information.
     809                 :  *
     810                 :  * Note that these coordinates refer to the raw grid, and are in the units
     811                 :  * specified by the #UNITS field.  See GXFGetPosition() for a similar
     812                 :  * function that takes into account the #SENSE values similarly to
     813                 :  * GXFGetScanline().
     814                 :  *
     815                 :  * Note that the pixel values are considered to be point values in GXF,
     816                 :  * and thus the origin is for the first point.  If you consider the pixels
     817                 :  * to be areas, then the origin is for the center of the origin pixel, not
     818                 :  * the outer corner.
     819                 :  *
     820                 :  * @param hGXF the GXF file handle.
     821                 :  * @param pdfXOrigin X position of the origin in the base coordinate system.
     822                 :  * @param pdfYOrigin Y position of the origin in the base coordinate system.
     823                 :  * @param pdfXPixelSize X pixel size in base coordinates.
     824                 :  * @param pdfYPixelSize Y pixel size in base coordinates.
     825                 :  * @param pdfRotation rotation in degrees counter-clockwise from the
     826                 :  * base coordinate system.
     827                 :  *
     828                 :  * @return Returns CE_None if successful, or CE_Failure if no posiitioning
     829                 :  * information was found in the file.
     830                 :  */
     831                 :  
     832                 : 
     833               0 : CPLErr GXFGetRawPosition( GXFHandle hGXF,
     834                 :                           double * pdfXOrigin, double * pdfYOrigin,
     835                 :                           double * pdfXPixelSize, double * pdfYPixelSize,
     836                 :                           double * pdfRotation )
     837                 : 
     838                 : {
     839               0 :     GXFInfo_t *psGXF = (GXFInfo_t *) hGXF;
     840                 :     
     841               0 :     if( pdfXOrigin != NULL )
     842               0 :         *pdfXOrigin = psGXF->dfXOrigin;
     843               0 :     if( pdfYOrigin != NULL )
     844               0 :         *pdfYOrigin = psGXF->dfYOrigin;
     845               0 :     if( pdfXPixelSize != NULL )
     846               0 :         *pdfXPixelSize = psGXF->dfXPixelSize;
     847               0 :     if( pdfYPixelSize != NULL )
     848               0 :         *pdfYPixelSize = psGXF->dfYPixelSize;
     849               0 :     if( pdfRotation != NULL )
     850               0 :         *pdfRotation = psGXF->dfRotation;
     851                 : 
     852               0 :     if( psGXF->dfXOrigin == 0.0 && psGXF->dfYOrigin == 0.0
     853               0 :         && psGXF->dfXPixelSize == 0.0 && psGXF->dfYPixelSize == 0.0 )
     854               0 :         return( CE_Failure );
     855                 :     else
     856               0 :         return( CE_None );
     857                 : }
     858                 : 
     859                 : 
     860                 : /************************************************************************/
     861                 : /*                           GXFGetPosition()                           */
     862                 : /************************************************************************/
     863                 : 
     864                 : /**
     865                 :  * Get the grid positioning information.
     866                 :  *
     867                 :  * Note that these coordinates refer to the grid positioning after taking
     868                 :  * into account the #SENSE flag (as is done by the GXFGetScanline()) function.
     869                 :  *
     870                 :  * Note that the pixel values are considered to be point values in GXF,
     871                 :  * and thus the origin is for the first point.  If you consider the pixels
     872                 :  * to be areas, then the origin is for the center of the origin pixel, not
     873                 :  * the outer corner.
     874                 :  *
     875                 :  * This function does not support vertically oriented images, nor does it
     876                 :  * properly transform rotation for images with a SENSE other than
     877                 :  * GXFS_UL_RIGHT.
     878                 :  *
     879                 :  * @param hGXF the GXF file handle.
     880                 :  * @param pdfXOrigin X position of the origin in the base coordinate system.
     881                 :  * @param pdfYOrigin Y position of the origin in the base coordinate system.
     882                 :  * @param pdfXPixelSize X pixel size in base coordinates.
     883                 :  * @param pdfYPixelSize Y pixel size in base coordinates.
     884                 :  * @param pdfRotation rotation in degrees counter-clockwise from the
     885                 :  * base coordinate system.
     886                 :  *
     887                 :  * @return Returns CE_None if successful, or CE_Failure if no posiitioning
     888                 :  * information was found in the file.
     889                 :  */
     890                 :  
     891                 : 
     892               0 : CPLErr GXFGetPosition( GXFHandle hGXF,
     893                 :                        double * pdfXOrigin, double * pdfYOrigin,
     894                 :                        double * pdfXPixelSize, double * pdfYPixelSize,
     895                 :                        double * pdfRotation )
     896                 : 
     897                 : {
     898               0 :     GXFInfo_t *psGXF = (GXFInfo_t *) hGXF;
     899                 :     double  dfCXOrigin, dfCYOrigin, dfCXPixelSize, dfCYPixelSize;
     900                 : 
     901               0 :     switch( psGXF->nSense )
     902                 :     {
     903                 :       case GXFS_UL_RIGHT:
     904               0 :         dfCXOrigin = psGXF->dfXOrigin;
     905               0 :         dfCYOrigin = psGXF->dfYOrigin;
     906               0 :         dfCXPixelSize = psGXF->dfXPixelSize;
     907               0 :         dfCYPixelSize = psGXF->dfYPixelSize;
     908               0 :         break;
     909                 :         
     910                 :       case GXFS_UR_LEFT:
     911               0 :         dfCXOrigin = psGXF->dfXOrigin
     912               0 :                    - (psGXF->nRawXSize-1) * psGXF->dfXPixelSize;
     913               0 :         dfCYOrigin = psGXF->dfYOrigin;
     914               0 :         dfCXPixelSize = psGXF->dfXPixelSize;
     915               0 :         dfCYPixelSize = psGXF->dfYPixelSize;
     916               0 :         break;
     917                 :         
     918                 :       case GXFS_LL_RIGHT:
     919               0 :         dfCXOrigin = psGXF->dfXOrigin;
     920               0 :         dfCYOrigin = psGXF->dfYOrigin
     921               0 :                      + (psGXF->nRawYSize-1) * psGXF->dfYPixelSize;
     922               0 :         dfCXPixelSize = psGXF->dfXPixelSize;
     923               0 :         dfCYPixelSize = psGXF->dfYPixelSize;
     924               0 :         break;
     925                 :         
     926                 :       case GXFS_LR_LEFT:
     927               0 :         dfCXOrigin = psGXF->dfXOrigin
     928               0 :                    - (psGXF->nRawXSize-1) * psGXF->dfXPixelSize;
     929               0 :         dfCYOrigin = psGXF->dfYOrigin
     930               0 :                      + (psGXF->nRawYSize-1) * psGXF->dfYPixelSize;
     931               0 :         dfCXPixelSize = psGXF->dfXPixelSize;
     932               0 :         dfCYPixelSize = psGXF->dfYPixelSize;
     933               0 :         break;
     934                 : 
     935                 :       default:
     936               0 :         CPLError( CE_Failure, CPLE_AppDefined,
     937                 :            "GXFGetPosition() doesn't support vertically organized images." );
     938               0 :         return CE_Failure;
     939                 :     }
     940                 : 
     941               0 :     if( pdfXOrigin != NULL )
     942               0 :         *pdfXOrigin = dfCXOrigin;
     943               0 :     if( pdfYOrigin != NULL )
     944               0 :         *pdfYOrigin = dfCYOrigin;
     945               0 :     if( pdfXPixelSize != NULL )
     946               0 :         *pdfXPixelSize = dfCXPixelSize;
     947               0 :     if( pdfYPixelSize != NULL )
     948               0 :         *pdfYPixelSize = dfCYPixelSize;
     949               0 :     if( pdfRotation != NULL )
     950               0 :         *pdfRotation = psGXF->dfRotation;
     951                 : 
     952               0 :     if( psGXF->dfXOrigin == 0.0 && psGXF->dfYOrigin == 0.0
     953               0 :         && psGXF->dfXPixelSize == 0.0 && psGXF->dfYPixelSize == 0.0 )
     954               0 :         return( CE_Failure );
     955                 :     else
     956               0 :         return( CE_None );
     957                 : }
     958                 : 
     959                 : 

Generated by: LCOV version 1.7