Main Page   Compound List   File List   Compound Members   File Members   Related Pages  

xtiff.c

00001 /*
00002  * xtiff.c
00003  *
00004  * Extended TIFF Directory GEO Tag Support.
00005  *
00006  *  You may use this file as a template to add your own
00007  *  extended tags to the library. Only the parts of the code
00008  *  marked with "XXX" require modification.
00009  *
00010  *  Author: Niles D. Ritter
00011  *
00012  *  Revisions:
00013  *    18 Sep 1995   -- Deprecated Integraph Matrix tag with new one.
00014  *                     Backward compatible support provided.  --NDR.
00015  */
00016  
00017 #include "xtiffiop.h"
00018 #include <stdio.h>
00019 
00020 /*  Tiff info structure.
00021  *
00022  *     Entry format:
00023  *        { TAGNUMBER, ReadCount, WriteCount, DataType, FIELDNUM, 
00024  *          OkToChange, PassDirCountOnSet, AsciiName }
00025  *
00026  *     For ReadCount, WriteCount, -1 = unknown.
00027  */
00028 
00029 static const TIFFFieldInfo xtiffFieldInfo[] = {
00030   
00031   /* XXX Insert Your tags here */
00032     { TIFFTAG_GEOPIXELSCALE,    -1,-1, TIFF_DOUBLE,     FIELD_GEOPIXELSCALE,
00033       TRUE,     TRUE,   "GeoPixelScale" },
00034     { TIFFTAG_INTERGRAPH_MATRIX,-1,-1, TIFF_DOUBLE,     FIELD_INTERGRAPH_MATRIX,
00035       TRUE,     TRUE,   "Intergraph TransformationMatrix" },
00036     { TIFFTAG_GEOTRANSMATRIX,   -1,-1, TIFF_DOUBLE,     FIELD_GEOTRANSMATRIX,
00037       TRUE,     TRUE,   "GeoTransformationMatrix" },
00038     { TIFFTAG_GEOTIEPOINTS,     -1,-1, TIFF_DOUBLE,     FIELD_GEOTIEPOINTS,
00039       TRUE,     TRUE,   "GeoTiePoints" },
00040     { TIFFTAG_GEOKEYDIRECTORY,-1,-1, TIFF_SHORT,        FIELD_GEOKEYDIRECTORY,
00041       TRUE,     TRUE,   "GeoKeyDirectory" },
00042     { TIFFTAG_GEODOUBLEPARAMS,  -1,-1, TIFF_DOUBLE,     FIELD_GEODOUBLEPARAMS,
00043       TRUE,     TRUE,   "GeoDoubleParams" },
00044     { TIFFTAG_GEOASCIIPARAMS,   -1,-1, TIFF_ASCII,      FIELD_GEOASCIIPARAMS,
00045       TRUE,     FALSE,  "GeoASCIIParams" },
00046 #ifdef JPL_TAG_SUPPORT
00047     { TIFFTAG_JPL_CARTO_IFD,     1, 1, TIFF_LONG,       FIELD_JPL_CARTO_IFD,
00048       TRUE,     TRUE,   "JPL Carto IFD offset" },  
00049 #endif
00050 };
00051 #define N(a)    (sizeof (a) / sizeof (a[0]))
00052 
00053 
00054 static void
00055 _XTIFFPrintDirectory(TIFF* tif, FILE* fd, long flags)
00056 {
00057         xtiff *xt = XTIFFDIR(tif);
00058         XTIFFDirectory *xd = &xt->xtif_dir;
00059         int i,j,num;
00060 
00061         /* call the inherited method */
00062         if (PARENT(xt,printdir))
00063                 (PARENT(xt,printdir))(tif,fd,flags);
00064 
00065         /* XXX Add field printing here */
00066 
00067         fprintf(fd,"--GeoTIFF Tags--\n");
00068 
00069         if (TIFFFieldSet(tif,FIELD_GEOTIEPOINTS))
00070         {
00071                 num = xd->xd_geodimensions[GEO_NUM_TIEPOINT];
00072                 fprintf(fd, "  Geo Tiepoints:");
00073                 if (num>6) fprintf(fd,"\n    ");
00074                 for (i=0;i<num;i+=6)
00075                 {
00076                    fprintf(fd," (");
00077                    for (j=0;j<3;j++)
00078                         fprintf(fd, " %f", xd->xd_geotiepoints[i+j]);
00079                    fprintf(fd,")->(");
00080                    for (j=3;j<6;j++)
00081                         fprintf(fd, " %f", xd->xd_geotiepoints[i+j]);
00082                    fprintf(fd,")\n");
00083                 }
00084         }
00085 
00086         if (TIFFFieldSet(tif,FIELD_GEOPIXELSCALE))
00087         {
00088                 num = xd->xd_geodimensions[GEO_NUM_PIXELSCALE];
00089                 fprintf(fd, "  Geo Pixel Scale: (");
00090                 for (j=0;j<num;j++)
00091                    fprintf(fd, " %f", xd->xd_geopixelscale[j]);
00092                 fprintf(fd, " )\n");
00093         }
00094 
00095         if (TIFFFieldSet(tif,FIELD_INTERGRAPH_MATRIX))
00096         {
00097                 num = xd->xd_geodimensions[GEO_NUM_IG_MATRIX];
00098                 fprintf(fd, "  Intergraph Transformation Matrix:\n");
00099                 for (i=0;num>3;num-=4)
00100                 {
00101                    for (j=0;j<4;j++)
00102                         fprintf(fd, " %8.2f", xd->xd_geomatrix[i++]);
00103                    fprintf(fd, "\n");
00104                 }
00105                 if (num)
00106                 {
00107                    for (j=0;j<num;j++)
00108                         fprintf(fd, " %8.2f", xd->xd_geomatrix[i++]);
00109                    fprintf(fd, "\n");
00110                 }
00111         }
00112 
00113         if (TIFFFieldSet(tif,FIELD_GEOTRANSMATRIX))
00114         {
00115                 num = xd->xd_geodimensions[GEO_NUM_MATRIX];
00116                 fprintf(fd, "  Geo Transformation Matrix:\n");
00117                 for (i=0;i<num;i+=4)
00118                 {
00119                    for (j=0;j<4;j++)
00120                         fprintf(fd, " %8.2f", xd->xd_geomatrix[i+j]);
00121                    fprintf(fd, "\n");
00122                 }
00123         }
00124 
00125         if (TIFFFieldSet(tif,FIELD_GEOKEYDIRECTORY))
00126         {
00127                 num = xd->xd_geodimensions[GEO_NUM_DIR];
00128                 fprintf(fd, "  GeoKey Directory:");
00129                 if (flags & TIFFPRINT_GEOKEYDIRECTORY) 
00130                 {
00131                         fprintf(fd, "\n");
00132                         for (i=0;i<num;i+=4)
00133                         {
00134                            for (j=0;j<4;j++)
00135                                 fprintf(fd, "  %8hu", xd->xd_geokeydirectory[i+j]);
00136                            fprintf(fd, "\n");
00137                         }
00138                 } else
00139                         fprintf(fd, "(present)\n");
00140 
00141         }
00142 
00143         if (TIFFFieldSet(tif,FIELD_GEODOUBLEPARAMS))
00144         {
00145                 num = xd->xd_geodimensions[GEO_NUM_DOUBLE];
00146                 fprintf(fd, "  GeoKey Double Params:");
00147                 if (flags & TIFFPRINT_GEOKEYPARAMS) 
00148                 {
00149                         fprintf(fd, "\n");
00150                         for (i=0;i<num;i++) 
00151                                 fprintf(fd, "  %8.2f", xd->xd_geodoubleparams[i]);
00152                         fprintf(fd, "\n");
00153                 } else
00154                         fprintf(fd, "(present)\n");
00155 
00156         }
00157 
00158         if (TIFFFieldSet(tif,FIELD_GEOASCIIPARAMS))
00159         {
00160                 if (flags & TIFFPRINT_GEOKEYPARAMS) 
00161                 {
00162                         _TIFFprintAsciiTag(fd,"GeoKey ASCII Parameters",
00163                                  xd->xd_geoasciiparams);
00164                 } else
00165                         fprintf(fd, "  GeoKey ASCII Parameters:(present)\n");
00166         }
00167 }
00168 
00169 static int
00170 _XTIFFVSetField(TIFF* tif, ttag_t tag, va_list ap)
00171 {
00172         xtiff *xt = XTIFFDIR(tif);
00173         XTIFFDirectory* xd = &xt->xtif_dir;
00174         int status = 1;
00175         uint16 num;
00176 
00177         /* va_start is called by the calling routine */
00178         
00179         switch (tag) {
00180                 /* XXX put extended tags here */
00181         case TIFFTAG_GEOKEYDIRECTORY:
00182                 xd->xd_geodimensions[GEO_NUM_DIR] = (uint16) va_arg(ap, int);
00183                 _TIFFsetShortArray(&xd->xd_geokeydirectory, va_arg(ap, uint16*),
00184                         (long) xd->xd_geodimensions[GEO_NUM_DIR]);
00185                 break;
00186         case TIFFTAG_GEODOUBLEPARAMS:
00187                 xd->xd_geodimensions[GEO_NUM_DOUBLE] = (uint16) va_arg(ap, int);
00188                 _TIFFsetDoubleArray(&xd->xd_geodoubleparams, va_arg(ap, double*),
00189                         (long) xd->xd_geodimensions[GEO_NUM_DOUBLE]);
00190                 break;
00191         case TIFFTAG_GEOTIEPOINTS:
00192                 xd->xd_geodimensions[GEO_NUM_TIEPOINT] = (uint16) va_arg(ap, int);
00193                 _TIFFsetDoubleArray(&xd->xd_geotiepoints, va_arg(ap, double*),
00194                         (long) xd->xd_geodimensions[GEO_NUM_TIEPOINT]);
00195                 break;
00196         case TIFFTAG_GEOTRANSMATRIX:
00197                 xd->xd_geodimensions[GEO_NUM_MATRIX] = (uint16) va_arg(ap, int);
00198                 _TIFFsetDoubleArray(&xd->xd_geomatrix, va_arg(ap, double*),
00199                         (long) xd->xd_geodimensions[GEO_NUM_MATRIX]);
00200                 break;
00201         case TIFFTAG_INTERGRAPH_MATRIX:
00202                 num = (uint16) va_arg(ap, int);
00203                 xd->xd_geodimensions[GEO_NUM_IG_MATRIX] = num;
00204                 _TIFFsetDoubleArray(&xd->xd_intergraph_matrix, va_arg(ap, double*),
00205                         (long) num);
00206                 /* For backward compatibility; note that we only
00207                  * allow the Intergraph tag to affect the GeoTIFF tag
00208                  * if the count is correct (Intergraph's version uses 17).
00209                  */
00210                 if (!TIFFFieldSet(tif,FIELD_GEOTRANSMATRIX) && num==16)
00211                         TIFFSetField(tif,TIFFTAG_GEOTRANSMATRIX,
00212                                 num, xd->xd_intergraph_matrix);
00213                 break;
00214         case TIFFTAG_GEOPIXELSCALE:
00215                 xd->xd_geodimensions[GEO_NUM_PIXELSCALE] = (uint16) va_arg(ap, int);
00216                 _TIFFsetDoubleArray(&xd->xd_geopixelscale, va_arg(ap, double*),
00217                         (long) xd->xd_geodimensions[GEO_NUM_PIXELSCALE]);
00218                 break;
00219         case TIFFTAG_GEOASCIIPARAMS:
00220                 _TIFFsetString(&xd->xd_geoasciiparams, va_arg(ap, char*));
00221                 break;
00222 #ifdef JPL_TAG_SUPPORT
00223         case TIFFTAG_JPL_CARTO_IFD:
00224                 xd->xd_jpl_ifd_offset = va_arg(ap, uint32);
00225                 break;
00226 #endif
00227         default:
00228                 /* call the inherited method */
00229                 return (PARENT(xt,vsetfield))(tif,tag,ap);
00230         }
00231         if (status) {
00232                 /* we have to override the print method here,
00233                  * after the compression tags have gotten to it.
00234                  * This makes sense because the only time we would
00235                  * need the extended print method is if an extended
00236                  * tag is set by either the reader or writer.
00237                  */
00238                 if (!(xt->xtif_flags & XTIFFP_PRINT))
00239                 {
00240                         PARENT(xt,printdir) =  TIFFMEMBER(tif,printdir);
00241                         TIFFMEMBER(tif,printdir) = _XTIFFPrintDirectory;
00242                         xt->xtif_flags |= XTIFFP_PRINT;
00243                 }
00244                 TIFFSetFieldBit(tif, _TIFFFieldWithTag(tif, tag)->field_bit);
00245                 tif->tif_flags |= TIFF_DIRTYDIRECT;
00246         }
00247         va_end(ap);
00248         return (status);
00249 }
00250 
00251 
00252 static int
00253 _XTIFFVGetField(TIFF* tif, ttag_t tag, va_list ap)
00254 {
00255         xtiff *xt = XTIFFDIR(tif);
00256         XTIFFDirectory* xd = &xt->xtif_dir;
00257 
00258         switch (tag) {
00259                 /* XXX insert your tags here */
00260         case TIFFTAG_GEOKEYDIRECTORY:
00261                 *va_arg(ap, uint16*) = xd->xd_geodimensions[GEO_NUM_DIR];
00262                 *va_arg(ap, uint16**) = xd->xd_geokeydirectory;
00263                 break;
00264         case TIFFTAG_GEODOUBLEPARAMS:
00265                 *va_arg(ap, uint16*) = xd->xd_geodimensions[GEO_NUM_DOUBLE];
00266                 *va_arg(ap, double**) = xd->xd_geodoubleparams;
00267                 break;
00268         case TIFFTAG_GEOTIEPOINTS:
00269                 *va_arg(ap, uint16*) = xd->xd_geodimensions[GEO_NUM_TIEPOINT];
00270                 *va_arg(ap, double**) = xd->xd_geotiepoints;
00271                 break;
00272         case TIFFTAG_GEOTRANSMATRIX:
00273                 *va_arg(ap, uint16*) = xd->xd_geodimensions[GEO_NUM_MATRIX];
00274                 *va_arg(ap, double**) = xd->xd_geomatrix;
00275                 break;
00276         case TIFFTAG_INTERGRAPH_MATRIX:
00277                 *va_arg(ap, uint16*) = xd->xd_geodimensions[GEO_NUM_IG_MATRIX];
00278                 *va_arg(ap, double**) = xd->xd_intergraph_matrix;
00279                 break;
00280         case TIFFTAG_GEOPIXELSCALE:
00281                 *va_arg(ap, uint16*) = xd->xd_geodimensions[GEO_NUM_PIXELSCALE];
00282                 *va_arg(ap, double**) = xd->xd_geopixelscale;
00283                 break;
00284         case TIFFTAG_GEOASCIIPARAMS:
00285                 *va_arg(ap, char**) = xd->xd_geoasciiparams;
00286                 break;
00287 #ifdef JPL_TAG_SUPPORT
00288         case TIFFTAG_JPL_CARTO_IFD:
00289                 *va_arg(ap, uint32*) = xd->xd_jpl_ifd_offset;
00290                 break;
00291 #endif
00292         default:
00293                 /* return inherited method */
00294                 return (PARENT(xt,vgetfield))(tif,tag,ap);
00295         }
00296         return (1);
00297 }
00298 
00299 #define CleanupField(member) {          \
00300     if (xd->member) {                   \
00301         _TIFFfree(xd->member);          \
00302         xd->member = 0;                 \
00303     }                                   \
00304 }
00305 /*
00306  * Release storage associated with a directory.
00307  */
00308 static void
00309 _XTIFFFreeDirectory(xtiff* xt)
00310 {
00311         XTIFFDirectory* xd = &xt->xtif_dir;
00312 
00313         /* 
00314          *  Purge all allocated memory except
00315          *  for the xtiff directory itself. This includes
00316          *  all fields that require a _TIFFsetXXX call in
00317          *  _XTIFFVSetField().
00318          */
00319         
00320         CleanupField(xd_geokeydirectory);
00321         CleanupField(xd_geodoubleparams);
00322         CleanupField(xd_geoasciiparams);
00323         CleanupField(xd_geomatrix);
00324         CleanupField(xd_geopixelscale);
00325         CleanupField(xd_geotiepoints);
00326         CleanupField(xd_intergraph_matrix);
00327         
00328 }
00329 #undef CleanupField
00330 
00331 static void _XTIFFLocalDefaultDirectory(TIFF *tif)
00332 {
00333         xtiff *xt = XTIFFDIR(tif);
00334 
00335         /* Install the extended Tag field info */
00336         _TIFFMergeFieldInfo(tif, xtiffFieldInfo, N(xtiffFieldInfo));
00337 
00338         /*
00339          *  free up any dynamically allocated arrays
00340          *  before the new directory is read in.
00341          */
00342          
00343         _XTIFFFreeDirectory(xt);        
00344         _TIFFmemset(xt,0,sizeof(xtiff));
00345 
00346         /* Override the tag access methods */
00347 
00348         PARENT(xt,vsetfield) =  TIFFMEMBER(tif,vsetfield);
00349         TIFFMEMBER(tif,vsetfield) = _XTIFFVSetField;
00350         PARENT(xt,vgetfield) =  TIFFMEMBER(tif,vgetfield);
00351         TIFFMEMBER(tif,vgetfield) = _XTIFFVGetField;
00352 
00353         /* 
00354          * XXX Set up any default values here.
00355          */
00356         
00357         /* NO DEFAULT GEOTIFF Values !*/
00358 
00359 }
00360 
00361 
00362 
00363 /**********************************************************************
00364  *    Nothing below this line should need to be changed.
00365  **********************************************************************/
00366 
00367 static TIFFExtendProc _ParentExtender;
00368 
00369 /*
00370  *  This is the callback procedure, and is
00371  *  called by the DefaultDirectory method
00372  *  every time a new TIFF directory is opened.
00373  */
00374 
00375 static void
00376 _XTIFFDefaultDirectory(TIFF *tif)
00377 {
00378         xtiff *xt;
00379         
00380         /* Allocate Directory Structure if first time, and install it */
00381         if (!(tif->tif_flags & XTIFF_INITIALIZED))
00382         {
00383                 xt = _TIFFmalloc(sizeof(xtiff));
00384                 if (!xt)
00385                 {
00386                         /* handle memory allocation failure here ! */
00387                         return;
00388                 }
00389                 _TIFFmemset(xt,0,sizeof(xtiff));
00390                 /*
00391                  * Install into TIFF structure.
00392                  */
00393                 TIFFMEMBER(tif,clientdir) = (tidata_t)xt;
00394                 tif->tif_flags |= XTIFF_INITIALIZED; /* dont do this again! */
00395         }
00396         
00397         /* set up our own defaults */
00398         _XTIFFLocalDefaultDirectory(tif);
00399 
00400         /* Since an XTIFF client module may have overridden
00401          * the default directory method, we call it now to
00402          * allow it to set up the rest of its own methods.
00403          */
00404 
00405         if (_ParentExtender) 
00406                 (*_ParentExtender)(tif);
00407 
00408 }
00409 
00410 /*
00411  *  XTIFF Initializer -- sets up the callback
00412  *   procedure for the TIFF module.
00413  */
00414 
00415 static
00416 void _XTIFFInitialize(void)
00417 {
00418         static int first_time=1;
00419         
00420         if (! first_time) return; /* Been there. Done that. */
00421         first_time = 0;
00422         
00423         /* Grab the inherited method and install */
00424         _ParentExtender = TIFFSetTagExtender(_XTIFFDefaultDirectory);
00425 }
00426 
00427 
00450 TIFF*
00451 XTIFFOpen(const char* name, const char* mode)
00452 {
00453         TIFF *tif;
00454 
00455         /* Set up the callback */
00456         _XTIFFInitialize();     
00457         
00458         /* Open the file; the callback will set everything up
00459          */
00460         tif = TIFFOpen(name, mode);
00461         if (!tif) return tif;
00462         
00463         return tif;
00464 }
00465 
00466 TIFF*
00467 XTIFFFdOpen(int fd, const char* name, const char* mode)
00468 {
00469         TIFF *tif;
00470 
00471         /* Set up the callback */
00472         _XTIFFInitialize();     
00473 
00474         /* Open the file; the callback will set everything up
00475          */
00476         tif = TIFFFdOpen(fd, name, mode);
00477         if (!tif) return tif;
00478         
00479         return tif;
00480 }
00481 
00492 void
00493 XTIFFClose(TIFF *tif)
00494 {
00495         xtiff *xt = XTIFFDIR(tif);
00496         
00497         /* call inherited function first */
00498         TIFFClose(tif);
00499         
00500         /* Free up extended allocated memory */
00501         _XTIFFFreeDirectory(xt);
00502         _TIFFfree(xt);
00503 }

Generated at Sun Mar 4 23:32:45 2001 for libgeotiff by doxygen1.2.3-20001105 written by Dimitri van Heesch, © 1997-2000