/* returns the value of TIFF tag <tag>, or if * the value is an array, returns an allocated buffer * containing the values. Allocate a copy of the actual * buffer, sized up for updating. */ static int _GTIFGetField (tiff_t *tif, pinfo_t tag, int *count, void *val ) { int status; unsigned short scount=0; char *tmp; char *value; gsize_t size = _gtiff_size[_GTIFTagType (tif,tag)]; if (_GTIFTagType(tif, tag) == TYPE_ASCII) { status = TIFFGetField((TIFF *)tif,tag,&tmp); if (!status) return status; scount = (unsigned short) (strlen(tmp)+1); } else status = TIFFGetField((TIFF *)tif,tag,&scount,&tmp); if (!status) return status; *count = scount; value = (char *)_GTIFcalloc( (scount+MAX_VALUES)*size); if (!value) return 0; _TIFFmemcpy( value, tmp, size * scount); *(char **)val = value; return status; }
static int ReadTag(GTIF *gt,GTIFReadMethod scan,void *aux) { int i,j,tag; char *vptr; char tagname[100]; double *data,*dptr; int count,nrows,ncols,num; char message[1024]; scan(message,aux); if (!strncmp(message,FMT_TAGEND,8)) return 0; num=sscanf(message,"%[^( ] (%d,%d):\n",tagname,&nrows,&ncols); if (num!=3) return StringError(message); tag = GTIFTagCode(tagname); if (tag < 0) return StringError(tagname); count = nrows*ncols; data = (double *) _GTIFcalloc(count * sizeof(double)); dptr = data; for (i=0; i<nrows; i++) { scan(message,aux); vptr = message; for (j=0; j<ncols; j++) { if (!sscanf(vptr,"%lg",dptr++)) return StringError(vptr); FINDCHAR(vptr,' '); SKIPWHITE(vptr); } } (gt->gt_methods.set)(gt->gt_tif, (pinfo_t) tag, count, data ); _GTIFFree( data ); return 1; }
/* returns the value of TIFF tag <tag>, or if * the value is an array, returns an allocated buffer * containing the values. Allocate a copy of the actual * buffer, sized up for updating. */ static int _GTIFGetField (tiff_t *tif, pinfo_t tag, int *count, void *val ) { int item_size, data_type; void *internal_value, *ret_value; if( !ST_GetKey( (ST_TIFF*) tif, (int) tag, count, &data_type, &internal_value ) ) return 0; if( data_type != ST_TagType( tag ) ) return 0; item_size = ST_TypeSize( data_type ); ret_value = (char *)_GTIFcalloc( *count * item_size ); if (!ret_value) return 0; _TIFFmemcpy( ret_value, internal_value, item_size * *count ); *(void **)val = ret_value; return 1; }
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 = GvCurrentVersion; header->hdr_rev_major = GvCurrentRevision; header->hdr_rev_minor = GvCurrentMinorRev; /* 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); 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])) 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; }
GTIF* GTIFNewWithMethods(void *tif, TIFFMethod* methods) { GTIF* gt=(GTIF*)0; int count,bufcount,index; GeoKey *keyptr; pinfo_t *data; KeyEntry *entptr; KeyHeader *header; TempKeyData tempData; memset( &tempData, 0, sizeof(tempData) ); gt = (GTIF*)_GTIFcalloc( sizeof(GTIF)); if (!gt) goto failure; /* install TIFF file and I/O methods */ gt->gt_tif = (tiff_t *)tif; memcpy( >->gt_methods, methods, sizeof(TIFFMethod) ); /* since this is an array, GTIF will allocate the memory */ if ( tif == NULL || !(gt->gt_methods.get)(tif, GTIFF_GEOKEYDIRECTORY, >->gt_nshorts, &data )) { /* No ProjectionInfo, create a blank one */ data=(pinfo_t*)_GTIFcalloc((4+MAX_VALUES)*sizeof(pinfo_t)); if (!data) goto failure; header = (KeyHeader *)data; header->hdr_version = GvCurrentVersion; header->hdr_rev_major = GvCurrentRevision; header->hdr_rev_minor = GvCurrentMinorRev; gt->gt_nshorts=sizeof(KeyHeader)/sizeof(pinfo_t); } else { /* resize data array so it can be extended if needed */ data = (pinfo_t*) _GTIFrealloc(data,(4+MAX_VALUES)*sizeof(pinfo_t)); } gt->gt_short = data; header = (KeyHeader *)data; if (header->hdr_version > GvCurrentVersion) goto failure; if (header->hdr_rev_major > GvCurrentRevision) { /* issue warning */ } /* If we got here, then the geokey can be parsed */ count = header->hdr_num_keys; if (count * sizeof(KeyEntry) >= (4 + MAX_VALUES) * sizeof(pinfo_t)) goto failure; gt->gt_num_keys = count; gt->gt_version = header->hdr_version; gt->gt_rev_major = header->hdr_rev_major; gt->gt_rev_minor = header->hdr_rev_minor; bufcount = count+MAX_KEYS; /* allow for expansion */ /* Get the PARAMS Tags, if any */ if (tif == NULL || !(gt->gt_methods.get)(tif, GTIFF_DOUBLEPARAMS, >->gt_ndoubles, >->gt_double )) { gt->gt_double=(double*)_GTIFcalloc(MAX_VALUES*sizeof(double)); if (!gt->gt_double) goto failure; } else { /* resize data array so it can be extended if needed */ gt->gt_double = (double*) _GTIFrealloc(gt->gt_double, (MAX_VALUES)*sizeof(double)); } if ( tif == NULL || !(gt->gt_methods.get)(tif, GTIFF_ASCIIPARAMS, &tempData.tk_asciiParamsLength, &tempData.tk_asciiParams )) { tempData.tk_asciiParams = 0; tempData.tk_asciiParamsLength = 0; } else { /* last NULL doesn't count; "|" used for delimiter */ --tempData.tk_asciiParamsLength; } /* allocate space for GeoKey array and its index */ gt->gt_keys = (GeoKey *)_GTIFcalloc( sizeof(GeoKey)*bufcount); if (!gt->gt_keys) goto failure; gt->gt_keyindex = (int *)_GTIFcalloc( sizeof(int)*(MAX_KEYINDEX+1)); if (!gt->gt_keyindex) goto failure; /* Loop to get all GeoKeys */ entptr = ((KeyEntry *)data) + 1; keyptr = gt->gt_keys; gt->gt_keymin = MAX_KEYINDEX; gt->gt_keymax = 0; for (index=1; index<=count; index++,entptr++) { if (!ReadKey(gt, &tempData, entptr, ++keyptr)) goto failure; /* Set up the index (start at 1, since 0=unset) */ gt->gt_keyindex[entptr->ent_key] = index; } if( tempData.tk_asciiParams != NULL ) _GTIFFree( tempData.tk_asciiParams ); return gt; failure: /* Notify of error */ if( tempData.tk_asciiParams != NULL ) _GTIFFree( tempData.tk_asciiParams ); GTIFFree (gt); return (GTIF *)0; }
static int ReadKey(GTIF* gt, TempKeyData* tempData, KeyEntry* entptr, GeoKey* keyptr) { int offset,count; keyptr->gk_key = entptr->ent_key; keyptr->gk_count = entptr->ent_count; count = entptr->ent_count; offset = entptr->ent_val_offset; if (gt->gt_keymin > keyptr->gk_key) gt->gt_keymin=keyptr->gk_key; if (gt->gt_keymax < keyptr->gk_key) gt->gt_keymax=keyptr->gk_key; if (entptr->ent_location) keyptr->gk_type = (gt->gt_methods.type)(gt->gt_tif,entptr->ent_location); else keyptr->gk_type = (gt->gt_methods.type)(gt->gt_tif,GTIFF_GEOKEYDIRECTORY); switch (entptr->ent_location) { case GTIFF_LOCAL: /* store value into data value */ *(pinfo_t *)(&keyptr->gk_data) = entptr->ent_val_offset; break; case GTIFF_GEOKEYDIRECTORY: keyptr->gk_data = (char *)(gt->gt_short+offset); if (gt->gt_nshorts < offset+count) gt->gt_nshorts = offset+count; break; case GTIFF_DOUBLEPARAMS: keyptr->gk_data = (char *)(gt->gt_double+offset); if (gt->gt_ndoubles < offset+count) gt->gt_ndoubles = offset+count; break; case GTIFF_ASCIIPARAMS: if( offset + count == tempData->tk_asciiParamsLength + 1 && count > 0 ) { /* some vendors seem to feel they should not use the terminating '|' char, but do include a terminating '\0' which we lose in the low level reading code. If this is the case, drop the extra character */ count--; } else if (offset < tempData->tk_asciiParamsLength && offset + count > tempData->tk_asciiParamsLength ) { count = tempData->tk_asciiParamsLength - offset; /* issue warning... if we could */ } else if (offset + count > tempData->tk_asciiParamsLength) return (0); keyptr->gk_count = MAX(1,count+1); keyptr->gk_data = (char *) _GTIFcalloc (keyptr->gk_count); _GTIFmemcpy (keyptr->gk_data, tempData->tk_asciiParams + offset, count); if( keyptr->gk_data[MAX(0,count-1)] == '|' ) { keyptr->gk_data[MAX(0,count-1)] = '\0'; keyptr->gk_count = count; } else keyptr->gk_data[MAX(0,count)] = '\0'; break; default: return 0; /* failure */ } keyptr->gk_size = _gtiff_size[keyptr->gk_type]; return 1; /* success */ }
static int ReadKey(GTIF *gt, GTIFReadMethod scan, void *aux) { tagtype_t ktype; int count,outcount; int vals_now,i; geokey_t key; int icode; pinfo_t code; short *sptr; char name[1000]; char type[20]; double data[100]; double *dptr; char *vptr; int num; char message[2048]; scan(message,aux); if (!strncmp(message,FMT_KEYEND,8)) return 0; num=sscanf(message,"%[^( ] (%[^,],%d):\n",name,type,&count); if (num!=3) return StringError(message); vptr = message; FINDCHAR(vptr,':'); if (!*vptr) return StringError(message); vptr+=2; if( GTIFKeyCode(name) < 0 ) return StringError(name); else key = (geokey_t) GTIFKeyCode(name); if( GTIFTypeCode(type) < 0 ) return StringError(type); else ktype = (tagtype_t) GTIFTypeCode(type); /* skip white space */ SKIPWHITE(vptr); if (!*vptr) return StringError(message); switch (ktype) { case TYPE_ASCII: { char *cdata; int out_char = 0; FINDCHAR(vptr,'"'); if (!*vptr) return StringError(message); cdata = (char *) _GTIFcalloc( count+1 ); vptr++; while( out_char < count-1 ) { if( *vptr == '\0' ) break; else if( vptr[0] == '\\' && vptr[1] == 'n' ) { cdata[out_char++] = '\n'; vptr += 2; } else if( vptr[0] == '\\' && vptr[1] == '\\' ) { cdata[out_char++] = '\\'; vptr += 2; } else cdata[out_char++] = *(vptr++); } if( out_char < count-1 ) return StringError(message); if( *vptr != '"' ) return StringError(message); cdata[count-1] = '\0'; GTIFKeySet(gt,key,ktype,count,cdata); _GTIFFree( cdata ); } break; case TYPE_DOUBLE: outcount = count; for (dptr = data; count > 0; count-= vals_now) { vals_now = count > 3? 3: count; for (i=0; i<vals_now; i++,dptr++) { if (!sscanf(vptr,"%lg" ,dptr)) StringError(vptr); FINDCHAR(vptr,' '); SKIPWHITE(vptr); } if (vals_now<count) { scan(message,aux); vptr = message; } } if (outcount==1) GTIFKeySet(gt,key,ktype,outcount,data[0]); else GTIFKeySet(gt,key,ktype,outcount,data); break; case TYPE_SHORT: if (count==1) { icode = GTIFValueCode(key,vptr); if (icode < 0) return StringError(vptr); code = (pinfo_t) icode; GTIFKeySet(gt,key,ktype,count,code); } else /* multi-valued short - no such thing yet */ { char* cdata; memcpy(&cdata, &data, sizeof(void*)); sptr = (short *)cdata; outcount = count; for (; count > 0; count-= vals_now) { vals_now = count > 3? 3: count; for (i=0; i<vals_now; i++,sptr++) { int work_int; /* note: FMT_SHORT (%11hd) not supported on IRIX */ sscanf(message,"%11d",&work_int); *sptr = (short) work_int; scan(message,aux); } if (vals_now<count) { scan(message,aux); vptr = message; } } GTIFKeySet(gt,key,ktype,outcount,sptr); } break; default: return -1; } return 1; }