Codebase list libgeotiff / scrub-obsolete/main geo_write.c
scrub-obsolete/main

Tree @scrub-obsolete/main (Download .tar.gz)

geo_write.c @scrub-obsolete/main

72368f0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34b035e
 
72368f0
 
 
 
34b035e
72368f0
 
 
 
 
 
 
 
 
 
 
34b035e
72368f0
 
 
 
34b035e
72368f0
 
 
 
 
 
 
 
 
34b035e
72368f0
 
 
59777cb
 
 
34b035e
72368f0
 
 
 
 
 
 
 
 
 
 
 
 
73d5521
 
72368f0
 
 
 
 
 
 
 
73d5521
 
 
 
 
 
 
 
34b035e
 
72368f0
34b035e
 
72368f0
 
 
 
 
 
 
 
 
 
34b035e
72368f0
 
 
 
 
 
 
 
 
 
 
 
 
 
34b035e
72368f0
 
 
 
 
 
 
 
 
34b035e
72368f0
 
 
34b035e
72368f0
 
 
73d5521
72368f0
 
34b035e
72368f0
 
 
 
 
 
 
 
 
34b035e
72368f0
 
 
73d5521
 
72368f0
 
 
 
 
 
 
 
 
 
34b035e
72368f0
 
 
 
34b035e
72368f0
 
 
 
 
 
 
 
 
73d5521
 
 
 
 
 
72368f0
 
 
 
 
 
34b035e
72368f0
 
 
 
 
 
34b035e
72368f0
 
 
 
 
 
 
/**********************************************************************
 *
 *  geo_write.c  -- Public routines for GEOTIFF GeoKey access.
 *
 *    Written By: Niles D. Ritter.
 *
 *  copyright (c) 1995   Niles D. Ritter
 *
 *  Permission granted to use this software, so long as this copyright
 *  notice accompanies any source code derived therefrom.
 *
 **********************************************************************/

#include "geotiffio.h"   /* public interface        */
#include "geo_tiffp.h" /* external TIFF interface */
#include "geo_keyp.h"  /* private interface       */

static int WriteKey(GTIF* gt, TempKeyData* tempData,
                    KeyEntry* entptr, GeoKey* keyptr);
static int SortKeys(GTIF* gt,int *sortkeys);


/**
This function flushes all the GeoTIFF keys that have been set with the
GTIFKeySet() function into the associated
TIFF file.

@param gt The GeoTIFF handle returned by GTIFNew.

GTIFWriteKeys() should be called before
GTIFFree() is used to deallocate a GeoTIFF access handle.
 */

int GTIFWriteKeys(GTIF *gt)
{
    int i;
    GeoKey *keyptr;
    KeyEntry *entptr;
    KeyHeader *header;
    TempKeyData tempData;
    int sortkeys[MAX_KEYS];

    if (!(gt->gt_flags & FLAG_FILE_MODIFIED)) return 1;

    if( gt->gt_tif == NULL )
        return 0;

    tempData.tk_asciiParams = 0;
    tempData.tk_asciiParamsLength = 0;
    tempData.tk_asciiParamsOffset = 0;

    /*  Sort the Keys into numerical order */
    if (!SortKeys(gt,sortkeys))
    {
        /* XXX error: a key was not recognized */
    }

    /* Set up header of ProjectionInfo tag */
    header = (KeyHeader *)gt->gt_short;
    header->hdr_num_keys = (pinfo_t) gt->gt_num_keys;
    header->hdr_version  = gt->gt_version;
    header->hdr_rev_major  = gt->gt_rev_major;
    header->hdr_rev_minor  = gt->gt_rev_minor;

    /* Sum up the ASCII tag lengths */
    for (i = 0; i < gt->gt_num_keys; i++)
    {
        keyptr = gt->gt_keys + sortkeys[i];
        if (keyptr->gk_type == TYPE_ASCII)
        {
            tempData.tk_asciiParamsLength += keyptr->gk_count;
        }
    }
    if (tempData.tk_asciiParamsLength > 0)
    {
        tempData.tk_asciiParams =
            (char *)_GTIFcalloc(tempData.tk_asciiParamsLength + 1);
        if( tempData.tk_asciiParams == NULL )
            return 0;
        tempData.tk_asciiParams[tempData.tk_asciiParamsLength] = '\0';
    }

    /* Set up the rest of SHORT array properly */
    keyptr = gt->gt_keys;
    entptr = (KeyEntry*)(gt->gt_short + 4);
    for (i=0; i< gt->gt_num_keys; i++,entptr++)
    {
        if (!WriteKey(gt,&tempData,entptr,keyptr+sortkeys[i]))
        {
            if (tempData.tk_asciiParamsLength > 0)
            {
                _GTIFFree (tempData.tk_asciiParams);
            }
            return 0;
        }
    }

    /* Write out the Key Directory */
    (gt->gt_methods.set)(gt->gt_tif, GTIFF_GEOKEYDIRECTORY, gt->gt_nshorts, gt->gt_short );

    /* Write out the params directories */
    if (gt->gt_ndoubles)
        (gt->gt_methods.set)(gt->gt_tif, GTIFF_DOUBLEPARAMS, gt->gt_ndoubles, gt->gt_double );
    if (tempData.tk_asciiParamsLength > 0)
    {
        /* just to be safe */
        tempData.tk_asciiParams[tempData.tk_asciiParamsLength] = '\0';
        (gt->gt_methods.set)(gt->gt_tif,
                             GTIFF_ASCIIPARAMS, 0, tempData.tk_asciiParams);
    }

    gt->gt_flags &= ~FLAG_FILE_MODIFIED;

    if (tempData.tk_asciiParamsLength > 0)
    {
        _GTIFFree (tempData.tk_asciiParams);
    }
    return 1;
}

/**********************************************************************
 *
 *                        Private Routines
 *
 **********************************************************************/

/*
 * Given GeoKey, write out the KeyEntry entries, returning 0 if failure.
 *  This is the exact complement of ReadKey().
 */

static int WriteKey(GTIF* gt, TempKeyData* tempData,
                    KeyEntry* entptr, GeoKey* keyptr)
{
    int count;

    entptr->ent_key = (pinfo_t) keyptr->gk_key;
    entptr->ent_count = (pinfo_t) keyptr->gk_count;
    count = entptr->ent_count;

    if (count==1 && keyptr->gk_type==TYPE_SHORT)
    {
        entptr->ent_location = GTIFF_LOCAL;
        memcpy(&(entptr->ent_val_offset), &keyptr->gk_data, sizeof(pinfo_t));
        return 1;
    }

    switch (keyptr->gk_type)
    {
      case TYPE_SHORT:
        entptr->ent_location = GTIFF_GEOKEYDIRECTORY;
        entptr->ent_val_offset = (pinfo_t)
            ((pinfo_t*)keyptr->gk_data - gt->gt_short);
        break;
      case TYPE_DOUBLE:
        entptr->ent_location = GTIFF_DOUBLEPARAMS;
        entptr->ent_val_offset = (pinfo_t)
            ((double*)keyptr->gk_data - gt->gt_double);
        break;
      case TYPE_ASCII:
        if( tempData->tk_asciiParams == NULL )
            return 0;
        entptr->ent_location = GTIFF_ASCIIPARAMS;
        entptr->ent_val_offset = (pinfo_t) tempData->tk_asciiParamsOffset;
        _GTIFmemcpy (tempData->tk_asciiParams + tempData->tk_asciiParamsOffset
                     , keyptr->gk_data, keyptr->gk_count);
        tempData->tk_asciiParams[tempData->tk_asciiParamsOffset+keyptr->gk_count-1] = '|';
        tempData->tk_asciiParamsOffset += keyptr->gk_count;
        break;
      default:
        return 0; /* failure */
    }

    return 1; /* success */
}


/*
 * Numerically sort the GeoKeys.
 * We just do a linear search through
 * the list and pull out the keys that were set.
 */

static int SortKeys(GTIF* gt,int *sortkeys)
{
    int i, did_work;

    /* A bit convoluted to make Clang Static Analyzer happy */
    if( gt->gt_num_keys <= 0 )
        return 1;

    sortkeys[0] = 1;
    for( i = 1; i < gt->gt_num_keys; i++ )
        sortkeys[i] = i+1;

    do {  /* simple bubble sort */
        did_work = 0;
        for( i = 0; i < gt->gt_num_keys-1; i++ )
        {
            if( gt->gt_keys[sortkeys[i]].gk_key
                > gt->gt_keys[sortkeys[i+1]].gk_key )
            {
                /* swap keys in sort list */
                int j = sortkeys[i];
                sortkeys[i] = sortkeys[i+1];
                sortkeys[i+1] = j;

                did_work = 1;
            }
        }
    } while( did_work );

    return 1;
}