LCOV - code coverage report
Current view: top level - frmts/gtiff/libgeotiff - geo_new.c (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 101 158 63.9 %
Date: 2024-05-04 12:52:34 Functions: 4 8 50.0 %

          Line data    Source code
       1             : /**********************************************************************
       2             :  *
       3             :  *  geo_new.c  -- Public routines for GEOTIFF GeoKey access.
       4             :  *
       5             :  *    Written By: Niles D. Ritter.
       6             :  *
       7             :  *  copyright (c) 1995   Niles D. Ritter
       8             :  *
       9             :  *  Permission granted to use this software, so long as this copyright
      10             :  *  notice accompanies any products derived therefrom.
      11             :  *
      12             :  **********************************************************************/
      13             : 
      14             : #include <stdarg.h>
      15             : #include <stdio.h>
      16             : #include <string.h>
      17             : 
      18             : #include "geotiffio.h"   /* public interface        */
      19             : #include "geo_tiffp.h" /* external TIFF interface */
      20             : #include "geo_keyp.h"  /* private interface       */
      21             : #include "geo_simpletags.h"
      22             : 
      23             : /* private local routines */
      24             : static int ReadKey(GTIF* gt, TempKeyData* tempData,
      25             :                    KeyEntry* entptr, GeoKey* keyptr);
      26             : 
      27             : 
      28           0 : static void GTIFErrorFunction(GTIF* gt, int level, const char* msg, ...)
      29             : {
      30             :     (void)gt;
      31             :     va_list list;
      32             : 
      33           0 :     va_start(list, msg);
      34           0 :     if( level == LIBGEOTIFF_WARNING )
      35           0 :         fprintf(stderr, "Warning: ");
      36           0 :     else if( level == LIBGEOTIFF_ERROR )
      37           0 :         fprintf(stderr, "Error: ");
      38           0 :     vfprintf(stderr, msg, list);
      39           0 :     fprintf(stderr, "\n");
      40           0 :     va_end(list);
      41           0 : }
      42             : 
      43             : /**********************************************************************
      44             :  *
      45             :  *                        Public Routines
      46             :  *
      47             :  **********************************************************************/
      48             : 
      49             : 
      50             : /**
      51             :  * Given an open TIFF file, look for GTIF keys and
      52             :  *  values and return GTIF structure.
      53             : 
      54             : This function creates a GeoTIFF information interpretation handle
      55             : (GTIF *) based on a passed in TIFF handle originally from
      56             : XTIFFOpen().  Even though the argument
      57             : (<b>tif</b>) is shown as type <tt>void *</tt>, it is really normally
      58             : of type <tt>TIFF *</tt>.<p>
      59             : 
      60             : The returned GTIF handle can be used to read or write GeoTIFF tags
      61             : using the various GTIF functions.  The handle should be destroyed using
      62             : GTIFFree() before the file is closed with TIFFClose().<p>
      63             : 
      64             : If the file accessed has no GeoTIFF keys, an valid (but empty) GTIF is
      65             : still returned.  GTIFNew() is used both for existing files being read, and
      66             : for new TIFF files that will have GeoTIFF tags written to them.<p>
      67             : 
      68             :  */
      69             : 
      70         816 : GTIF* GTIFNew(void *tif)
      71             : 
      72             : {
      73         816 :     return GTIFNewEx( tif, GTIFErrorFunction, NULL );
      74             : }
      75             : 
      76       21206 : GTIF* GTIFNewEx(void *tif,
      77             :                 GTErrorCallback error_callback, void* user_data)
      78             : 
      79             : {
      80             :     TIFFMethod default_methods;
      81       21206 :     _GTIFSetDefaultTIFF( &default_methods );
      82             : 
      83       21206 :     return GTIFNewWithMethodsEx( tif, &default_methods,
      84             :                                  error_callback, user_data );
      85             : }
      86             : 
      87           0 : GTIF *GTIFNewSimpleTags( void *tif )
      88             : 
      89             : {
      90             :     TIFFMethod default_methods;
      91           0 :     GTIFSetSimpleTagsMethods( &default_methods );
      92             : 
      93           0 :     return GTIFNewWithMethods( tif, &default_methods );
      94             : }
      95             : 
      96             : /************************************************************************/
      97             : /*                         GTIFNewWithMethods()                         */
      98             : /*                                                                      */
      99             : /*      Create a new geotiff, passing in the methods structure to       */
     100             : /*      support not libtiff implementations without replacing the       */
     101             : /*      default methods.                                                */
     102             : /************************************************************************/
     103             : 
     104           0 : GTIF* GTIFNewWithMethods(void *tif, TIFFMethod* methods)
     105             : {
     106           0 :     return GTIFNewWithMethodsEx(tif, methods, GTIFErrorFunction, NULL);
     107             : }
     108             : 
     109       21206 : GTIF* GTIFNewWithMethodsEx(void *tif, TIFFMethod* methods,
     110             :                            GTErrorCallback error_callback, void* user_data)
     111             : {
     112             :     TempKeyData tempData;
     113       21206 :     memset( &tempData, 0, sizeof(tempData) );
     114             : 
     115       21206 :     GTIF* gt = (GTIF*)_GTIFcalloc( sizeof(GTIF));
     116       21206 :     if (!gt) goto failure;
     117             : 
     118       21206 :     gt->gt_error_callback = error_callback;
     119       21206 :     gt->gt_user_data = user_data;
     120             : 
     121             :     /* install TIFF file and I/O methods */
     122       21206 :     gt->gt_tif = (tiff_t *)tif;
     123       21206 :     memcpy( &gt->gt_methods, methods, sizeof(TIFFMethod) );
     124             : 
     125             :     /* since this is an array, GTIF will allocate the memory */
     126             :     pinfo_t *data;
     127       21206 :     if ( tif == NULL
     128       21206 :          || !(gt->gt_methods.get)(tif, GTIFF_GEOKEYDIRECTORY, &gt->gt_nshorts, &data ))
     129        9113 :     {
     130             :         /* No ProjectionInfo, create a blank one */
     131        9113 :         data=(pinfo_t*)_GTIFcalloc((4+MAX_VALUES)*sizeof(pinfo_t));
     132        9113 :         if (!data) goto failure;
     133        9113 :         KeyHeader *header = (KeyHeader *)data;
     134        9113 :         header->hdr_version = GvCurrentVersion;
     135        9113 :         header->hdr_rev_major = GvCurrentRevision;
     136        9113 :         header->hdr_rev_minor = GvCurrentMinorRev;
     137        9113 :         gt->gt_nshorts=sizeof(KeyHeader)/sizeof(pinfo_t);
     138             :     }
     139             :     else
     140             :     {
     141             :         /* resize data array so it can be extended if needed */
     142       12093 :         data = (pinfo_t*) _GTIFrealloc(data,(4+MAX_VALUES)*sizeof(pinfo_t));
     143             :     }
     144       21206 :     gt->gt_short = data;
     145       21206 :     KeyHeader *header = (KeyHeader *)data;
     146             : 
     147       21206 :     if (header->hdr_version > GvCurrentVersion) goto failure;
     148       21206 :     if (header->hdr_rev_major > GvCurrentRevision)
     149             :     {
     150             :         /* issue warning */
     151             :     }
     152             : 
     153             :     /* If we got here, then the geokey can be parsed */
     154       21206 :     const int count = header->hdr_num_keys;
     155             : 
     156       21206 :     if (count * sizeof(KeyEntry) >= (4 + MAX_VALUES) * sizeof(pinfo_t))
     157           0 :         goto failure;
     158             : 
     159       21206 :     gt->gt_num_keys = count;
     160       21206 :     gt->gt_version  = header->hdr_version;
     161       21206 :     gt->gt_rev_major  = header->hdr_rev_major;
     162       21206 :     gt->gt_rev_minor  = header->hdr_rev_minor;
     163             : 
     164       21206 :     const int bufcount = count + MAX_KEYS; /* allow for expansion */
     165             : 
     166             :     /* Get the PARAMS Tags, if any */
     167       21206 :     if (tif == NULL
     168       21206 :         || !(gt->gt_methods.get)(tif, GTIFF_DOUBLEPARAMS,
     169       21206 :                                  &gt->gt_ndoubles, &gt->gt_double ))
     170             :     {
     171       16962 :         gt->gt_double=(double*)_GTIFcalloc(MAX_VALUES*sizeof(double));
     172       16962 :         if (!gt->gt_double) goto failure;
     173             :     }
     174             :     else
     175             :     {
     176        4244 :         if( gt->gt_ndoubles > MAX_VALUES )
     177           0 :             goto failure;
     178             :         /* resize data array so it can be extended if needed */
     179        4244 :         gt->gt_double = (double*) _GTIFrealloc(gt->gt_double,
     180             :                                                (MAX_VALUES)*sizeof(double));
     181             :     }
     182             : 
     183       21206 :     if ( tif == NULL
     184       21206 :          || !(gt->gt_methods.get)(tif, GTIFF_ASCIIPARAMS,
     185             :                                   &tempData.tk_asciiParamsLength,
     186             :                                   &tempData.tk_asciiParams ))
     187             :     {
     188        9501 :         tempData.tk_asciiParams         = 0;
     189        9501 :         tempData.tk_asciiParamsLength   = 0;
     190             :     }
     191             :     else
     192             :     {
     193             :         /* last NULL doesn't count; "|" used for delimiter */
     194       11705 :         if( tempData.tk_asciiParamsLength > 0
     195       11705 :             && tempData.tk_asciiParams[tempData.tk_asciiParamsLength-1] == '\0')
     196             :         {
     197       11705 :             --tempData.tk_asciiParamsLength;
     198             :         }
     199             :     }
     200             : 
     201             :     /* allocate space for GeoKey array and its index */
     202       21206 :     gt->gt_keys = (GeoKey *)_GTIFcalloc( sizeof(GeoKey)*bufcount);
     203       21206 :     if (!gt->gt_keys) goto failure;
     204       21206 :     gt->gt_keyindex = (int *)_GTIFcalloc( sizeof(int)*(MAX_KEYINDEX+1));
     205       21206 :     if (!gt->gt_keyindex) goto failure;
     206             : 
     207             :     /*  Loop to get all GeoKeys */
     208       21206 :     KeyEntry *entptr = ((KeyEntry *)data) + 1;
     209       21206 :     GeoKey *keyptr = gt->gt_keys;
     210       21206 :     gt->gt_keymin = MAX_KEYINDEX;
     211       21206 :     gt->gt_keymax = 0;
     212       96508 :     for (int nIndex=1; nIndex<=count; nIndex++,entptr++)
     213             :     {
     214       75302 :         if (!ReadKey(gt, &tempData, entptr, ++keyptr))
     215           0 :             goto failure;
     216             : 
     217             :         /* Set up the index (start at 1, since 0=unset) */
     218       75302 :         gt->gt_keyindex[entptr->ent_key] = nIndex;
     219             :     }
     220             : 
     221       21206 :     if( tempData.tk_asciiParams != NULL )
     222       11705 :         _GTIFFree( tempData.tk_asciiParams );
     223             : 
     224       21206 :     return gt;
     225             : 
     226           0 :   failure:
     227             :     /* Notify of error */
     228           0 :     if( tempData.tk_asciiParams != NULL )
     229           0 :         _GTIFFree( tempData.tk_asciiParams );
     230           0 :     GTIFFree (gt);
     231           0 :     return (GTIF *)0;
     232             : }
     233             : 
     234             : /**********************************************************************
     235             :  *
     236             :  *                        Private Routines
     237             :  *
     238             :  **********************************************************************/
     239             : 
     240             : /*
     241             :  * Given KeyEntry, read in the GeoKey value location and set up
     242             :  *  the Key structure, returning 0 if failure.
     243             :  */
     244             : 
     245       75302 : static int ReadKey(GTIF* gt, TempKeyData* tempData,
     246             :                    KeyEntry* entptr, GeoKey* keyptr)
     247             : {
     248       75302 :     keyptr->gk_key = entptr->ent_key;
     249       75302 :     keyptr->gk_count = entptr->ent_count;
     250       75302 :     int count = entptr->ent_count;
     251       75302 :     const int offset = entptr->ent_val_offset;
     252       75302 :     if (gt->gt_keymin > keyptr->gk_key)  gt->gt_keymin=keyptr->gk_key;
     253       75302 :     if (gt->gt_keymax < keyptr->gk_key)  gt->gt_keymax=keyptr->gk_key;
     254             : 
     255       75302 :     if (entptr->ent_location)
     256       23842 :         keyptr->gk_type = (gt->gt_methods.type)(gt->gt_tif,entptr->ent_location);
     257             :     else
     258       51460 :         keyptr->gk_type = (gt->gt_methods.type)(gt->gt_tif,GTIFF_GEOKEYDIRECTORY);
     259             : 
     260       75302 :     switch (entptr->ent_location)
     261             :     {
     262       51460 :         case GTIFF_LOCAL:
     263             :             /* store value into data value */
     264       51460 :             if (count != 1 )
     265             :             {
     266           0 :                 if( gt->gt_error_callback )
     267             :                 {
     268           0 :                     gt->gt_error_callback(
     269             :                         gt,
     270             :                         LIBGEOTIFF_ERROR,
     271             :                         "Key %s of TIFFTagLocation=0 has count=%d, "
     272             :                         "whereas only 1 is legal.",
     273           0 :                         GTIFKeyName(keyptr->gk_key), count);
     274             :                 }
     275           0 :                 return 0;
     276             :             }
     277       51460 :             memcpy(&keyptr->gk_data, &(entptr->ent_val_offset), sizeof(pinfo_t));
     278       51460 :             break;
     279           0 :         case GTIFF_GEOKEYDIRECTORY:
     280           0 :             keyptr->gk_data = (char *)(gt->gt_short+offset);
     281           0 :             if (gt->gt_nshorts < offset+count)
     282             :             {
     283           0 :                 if( gt->gt_error_callback )
     284             :                 {
     285           0 :                     gt->gt_error_callback(
     286             :                         gt,
     287             :                         LIBGEOTIFF_ERROR,
     288             :                         "Key %s of type SHORT has offset=%d and count=%d, "
     289             :                         "but the GeoKeyDirectory tag has only %d values.",
     290           0 :                         GTIFKeyName(keyptr->gk_key),
     291             :                         offset, count, gt->gt_nshorts);
     292             :                 }
     293           0 :                 return 0;
     294             :             }
     295           0 :             break;
     296        9272 :         case GTIFF_DOUBLEPARAMS:
     297        9272 :             keyptr->gk_data = (char *)(gt->gt_double+offset);
     298        9272 :             if (gt->gt_ndoubles < offset+count)
     299             :             {
     300           0 :                 if( gt->gt_error_callback )
     301             :                 {
     302           0 :                     gt->gt_error_callback(
     303             :                         gt,
     304             :                         LIBGEOTIFF_ERROR,
     305             :                         "Key %s of type SHORT has offset=%d and count=%d, "
     306             :                         "but the GeoDoubleParams tag has only %d values.",
     307           0 :                         GTIFKeyName(keyptr->gk_key),
     308             :                         offset, count, gt->gt_ndoubles);
     309             :                 }
     310           0 :                 return 0;
     311             :             }
     312        9272 :             break;
     313       14570 :         case GTIFF_ASCIIPARAMS:
     314       14570 :             if( tempData->tk_asciiParams == NULL )
     315             :             {
     316           0 :                 if( gt->gt_error_callback )
     317             :                 {
     318           0 :                     gt->gt_error_callback(
     319             :                         gt,
     320             :                         LIBGEOTIFF_ERROR,
     321             :                         "Key %s is of type ASCII but GeoAsciiParams is "
     322             :                         "missing or corrupted.",
     323           0 :                         GTIFKeyName(keyptr->gk_key));
     324             :                 }
     325           0 :                 return 0;
     326             :             }
     327       14570 :             if( offset + count == tempData->tk_asciiParamsLength + 1
     328           7 :                 && count > 0 )
     329             :             {
     330             :                 /* some vendors seem to feel they should not use the
     331             :                    terminating '|' char, but do include a terminating '\0'
     332             :                    which we lose in the low level reading code.
     333             :                    If this is the case, drop the extra character */
     334           7 :                 count--;
     335             :             }
     336       14563 :             else if (offset < tempData->tk_asciiParamsLength
     337       14563 :                      && offset + count > tempData->tk_asciiParamsLength )
     338             :             {
     339           0 :                 if( gt->gt_error_callback )
     340             :                 {
     341           0 :                     gt->gt_error_callback(
     342             :                         gt,
     343             :                         LIBGEOTIFF_WARNING,
     344             :                         "Key %s of type ASCII has offset=%d and count=%d, but "
     345             :                         "the GeoAsciiParams tag has only %d bytes. "
     346             :                         "Truncating the value of the key.",
     347           0 :                         GTIFKeyName(keyptr->gk_key), offset, count,
     348             :                         tempData->tk_asciiParamsLength);
     349             :                 }
     350           0 :                 count = tempData->tk_asciiParamsLength - offset;
     351             :             }
     352       14563 :             else if (offset + count > tempData->tk_asciiParamsLength)
     353             :             {
     354           0 :                 if( gt->gt_error_callback )
     355             :                 {
     356           0 :                     gt->gt_error_callback(
     357             :                         gt,
     358             :                         LIBGEOTIFF_ERROR,
     359             :                         "Key %s of type ASCII has offset=%d and count=%d, "
     360             :                         "but the GeoAsciiParams tag has only %d values.",
     361           0 :                         GTIFKeyName(keyptr->gk_key), offset, count,
     362             :                         tempData->tk_asciiParamsLength);
     363             :                 }
     364           0 :                 return 0;
     365             :             }
     366             : 
     367       14570 :             keyptr->gk_count = MAX(1,count+1);
     368       14570 :             keyptr->gk_data = (char *) _GTIFcalloc (keyptr->gk_count);
     369             : 
     370       14570 :             _GTIFmemcpy (keyptr->gk_data,
     371       14570 :                          tempData->tk_asciiParams + offset, count);
     372       14570 :             if( keyptr->gk_data[MAX(0,count-1)] == '|' )
     373             :             {
     374       14563 :                 keyptr->gk_data[MAX(0,count-1)] = '\0';
     375       14563 :                 keyptr->gk_count = count;
     376             :             }
     377             :             else
     378           7 :                 keyptr->gk_data[MAX(0,count)] = '\0';
     379       14570 :             break;
     380           0 :         default:
     381           0 :             if( gt->gt_error_callback )
     382             :             {
     383           0 :                 gt->gt_error_callback(
     384             :                     gt,
     385             :                     LIBGEOTIFF_ERROR,
     386             :                     "Key %d of unknown type.",
     387             :                     keyptr->gk_key);
     388             :             }
     389           0 :             return 0; /* failure */
     390             :     }
     391       75302 :     keyptr->gk_size = _gtiff_size[keyptr->gk_type];
     392             : 
     393       75302 :     return 1; /* success */
     394             : }
     395             : 
     396           0 : void *GTIFGetUserData(GTIF *gtif)
     397             : {
     398           0 :     return gtif->gt_user_data;
     399             : }

Generated by: LCOV version 1.14