LCOV - code coverage report
Current view: top level - frmts/gtiff/libgeotiff - geo_write.c (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 75 89 84.3 %
Date: 2024-05-04 12:52:34 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /**********************************************************************
       2             :  *
       3             :  *  geo_write.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 source code derived therefrom.
      11             :  *
      12             :  **********************************************************************/
      13             : 
      14             : #include "geotiffio.h"   /* public interface        */
      15             : #include "geo_tiffp.h" /* external TIFF interface */
      16             : #include "geo_keyp.h"  /* private interface       */
      17             : 
      18             : static int WriteKey(GTIF* gt, TempKeyData* tempData,
      19             :                     KeyEntry* entptr, GeoKey* keyptr);
      20             : static int SortKeys(GTIF* gt,int *sortkeys);
      21             : 
      22             : 
      23             : /**
      24             : This function flushes all the GeoTIFF keys that have been set with the
      25             : GTIFKeySet() function into the associated
      26             : TIFF file.
      27             : 
      28             : @param gt The GeoTIFF handle returned by GTIFNew.
      29             : 
      30             : GTIFWriteKeys() should be called before
      31             : GTIFFree() is used to deallocate a GeoTIFF access handle.
      32             :  */
      33             : 
      34        2152 : int GTIFWriteKeys(GTIF *gt)
      35             : {
      36             : 
      37        2152 :     if (!(gt->gt_flags & FLAG_FILE_MODIFIED)) return 1;
      38             : 
      39        2142 :     if( gt->gt_tif == NULL )
      40           0 :         return 0;
      41             : 
      42             :     TempKeyData tempData;
      43        2142 :     tempData.tk_asciiParams = 0;
      44        2142 :     tempData.tk_asciiParamsLength = 0;
      45        2142 :     tempData.tk_asciiParamsOffset = 0;
      46             : 
      47             :     /*  Sort the Keys into numerical order */
      48             :     int sortkeys[MAX_KEYS];
      49        2142 :     if (!SortKeys(gt,sortkeys))
      50             :     {
      51             :         /* XXX error: a key was not recognized */
      52             :     }
      53             : 
      54             :     /* Set up header of ProjectionInfo tag */
      55        2142 :     KeyHeader *header = (KeyHeader *)gt->gt_short;
      56        2142 :     header->hdr_num_keys = (pinfo_t) gt->gt_num_keys;
      57        2142 :     header->hdr_version  = gt->gt_version;
      58        2142 :     header->hdr_rev_major  = gt->gt_rev_major;
      59        2142 :     header->hdr_rev_minor  = gt->gt_rev_minor;
      60             : 
      61             :     /* Sum up the ASCII tag lengths */
      62       17454 :     for (int i = 0; i < gt->gt_num_keys; i++)
      63             :     {
      64       15312 :         GeoKey *keyptr = gt->gt_keys + sortkeys[i];
      65       15312 :         if (keyptr->gk_type == TYPE_ASCII)
      66             :         {
      67        2847 :             tempData.tk_asciiParamsLength += keyptr->gk_count;
      68             :         }
      69             :     }
      70        2142 :     if (tempData.tk_asciiParamsLength > 0)
      71             :     {
      72        2025 :         tempData.tk_asciiParams =
      73        2025 :             (char *)_GTIFcalloc(tempData.tk_asciiParamsLength + 1);
      74        2025 :         if( tempData.tk_asciiParams == NULL )
      75           0 :             return 0;
      76        2025 :         tempData.tk_asciiParams[tempData.tk_asciiParamsLength] = '\0';
      77             :     }
      78             : 
      79             :     /* Set up the rest of SHORT array properly */
      80        2142 :     GeoKey *keyptr = gt->gt_keys;
      81        2142 :     KeyEntry *entptr = (KeyEntry*)(gt->gt_short + 4);
      82       17454 :     for (int i=0; i< gt->gt_num_keys; i++,entptr++)
      83             :     {
      84       15312 :         if (!WriteKey(gt,&tempData,entptr,keyptr+sortkeys[i]))
      85             :         {
      86           0 :             if (tempData.tk_asciiParamsLength > 0)
      87             :             {
      88           0 :                 _GTIFFree (tempData.tk_asciiParams);
      89             :             }
      90           0 :             return 0;
      91             :         }
      92             :     }
      93             : 
      94             :     /* Write out the Key Directory */
      95        2142 :     (gt->gt_methods.set)(gt->gt_tif, GTIFF_GEOKEYDIRECTORY, gt->gt_nshorts, gt->gt_short );
      96             : 
      97             :     /* Write out the params directories */
      98        2142 :     if (gt->gt_ndoubles)
      99        1292 :         (gt->gt_methods.set)(gt->gt_tif, GTIFF_DOUBLEPARAMS, gt->gt_ndoubles, gt->gt_double );
     100        2142 :     if (tempData.tk_asciiParamsLength > 0)
     101             :     {
     102             :         /* just to be safe */
     103        2025 :         tempData.tk_asciiParams[tempData.tk_asciiParamsLength] = '\0';
     104        2025 :         (gt->gt_methods.set)(gt->gt_tif,
     105        2025 :                              GTIFF_ASCIIPARAMS, 0, tempData.tk_asciiParams);
     106             :     }
     107             : 
     108        2142 :     gt->gt_flags &= ~FLAG_FILE_MODIFIED;
     109             : 
     110        2142 :     if (tempData.tk_asciiParamsLength > 0)
     111             :     {
     112        2025 :         _GTIFFree (tempData.tk_asciiParams);
     113             :     }
     114        2142 :     return 1;
     115             : }
     116             : 
     117             : /**********************************************************************
     118             :  *
     119             :  *                        Private Routines
     120             :  *
     121             :  **********************************************************************/
     122             : 
     123             : /*
     124             :  * Given GeoKey, write out the KeyEntry entries, returning 0 if failure.
     125             :  *  This is the exact complement of ReadKey().
     126             :  */
     127             : 
     128       15312 : static int WriteKey(GTIF* gt, TempKeyData* tempData,
     129             :                     KeyEntry* entptr, GeoKey* keyptr)
     130             : {
     131       15312 :     entptr->ent_key = (pinfo_t) keyptr->gk_key;
     132       15312 :     entptr->ent_count = (pinfo_t) keyptr->gk_count;
     133       15312 :     const int count = entptr->ent_count;
     134             : 
     135       15312 :     if (count==1 && keyptr->gk_type==TYPE_SHORT)
     136             :     {
     137        9565 :         entptr->ent_location = GTIFF_LOCAL;
     138        9565 :         memcpy(&(entptr->ent_val_offset), &keyptr->gk_data, sizeof(pinfo_t));
     139        9565 :         return 1;
     140             :     }
     141             : 
     142        5747 :     switch (keyptr->gk_type)
     143             :     {
     144           0 :       case TYPE_SHORT:
     145           0 :         entptr->ent_location = GTIFF_GEOKEYDIRECTORY;
     146           0 :         entptr->ent_val_offset = (pinfo_t)
     147           0 :             ((pinfo_t*)keyptr->gk_data - gt->gt_short);
     148           0 :         break;
     149        2900 :       case TYPE_DOUBLE:
     150        2900 :         entptr->ent_location = GTIFF_DOUBLEPARAMS;
     151        2900 :         entptr->ent_val_offset = (pinfo_t)
     152        2900 :             ((double*)keyptr->gk_data - gt->gt_double);
     153        2900 :         break;
     154        2847 :       case TYPE_ASCII:
     155        2847 :         if( tempData->tk_asciiParams == NULL )
     156           0 :             return 0;
     157        2847 :         entptr->ent_location = GTIFF_ASCIIPARAMS;
     158        2847 :         entptr->ent_val_offset = (pinfo_t) tempData->tk_asciiParamsOffset;
     159        2847 :         _GTIFmemcpy (tempData->tk_asciiParams + tempData->tk_asciiParamsOffset
     160        2847 :                      , keyptr->gk_data, keyptr->gk_count);
     161        2847 :         tempData->tk_asciiParams[tempData->tk_asciiParamsOffset+keyptr->gk_count-1] = '|';
     162        2847 :         tempData->tk_asciiParamsOffset += keyptr->gk_count;
     163        2847 :         break;
     164           0 :       default:
     165           0 :         return 0; /* failure */
     166             :     }
     167             : 
     168        5747 :     return 1; /* success */
     169             : }
     170             : 
     171             : 
     172             : /*
     173             :  * Numerically sort the GeoKeys.
     174             :  * We just do a linear search through
     175             :  * the list and pull out the keys that were set.
     176             :  */
     177             : 
     178        2142 : static int SortKeys(GTIF* gt,int *sortkeys)
     179             : {
     180             :     /* A bit convoluted to make Clang Static Analyzer happy */
     181        2142 :     if( gt->gt_num_keys <= 0 )
     182           0 :         return 1;
     183             : 
     184        2142 :     sortkeys[0] = 1;
     185       15312 :     for( int i = 1; i < gt->gt_num_keys; i++ )
     186       13170 :         sortkeys[i] = i+1;
     187             : 
     188             :     int did_work;
     189             :     do {  /* simple bubble sort */
     190        9111 :         did_work = 0;
     191       74556 :         for( int i = 0; i < gt->gt_num_keys-1; i++ )
     192             :         {
     193       65445 :             if( gt->gt_keys[sortkeys[i]].gk_key
     194       65445 :                 > gt->gt_keys[sortkeys[i+1]].gk_key )
     195             :             {
     196             :                 /* swap keys in sort list */
     197       19845 :                 int j = sortkeys[i];
     198       19845 :                 sortkeys[i] = sortkeys[i+1];
     199       19845 :                 sortkeys[i+1] = j;
     200             : 
     201       19845 :                 did_work = 1;
     202             :             }
     203             :         }
     204        9111 :     } while( did_work );
     205             : 
     206        2142 :     return 1;
     207             : }

Generated by: LCOV version 1.14