1 /****************************************************************************** 2 * $Id: tiffset.c,v 1.13 2008-01-01 15:46:28 fwarmerdam Exp $ 3 * 4 * Project: libtiff tools 5 * Purpose: Mainline for setting metadata in existing TIFF files. 6 * Author: Frank Warmerdam, [email protected] 7 * 8 ****************************************************************************** 9 * Copyright (c) 2000, Frank Warmerdam 10 * 11 * Permission to use, copy, modify, distribute, and sell this software and 12 * its documentation for any purpose is hereby granted without fee, provided 13 * that (i) the above copyright notices and this permission notice appear in 14 * all copies of the software and related documentation, and (ii) the names of 15 * Sam Leffler and Silicon Graphics may not be used in any advertising or 16 * publicity relating to the software without the specific, prior written 17 * permission of Sam Leffler and Silicon Graphics. 18 * 19 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 20 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 21 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. 22 * 23 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR 24 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, 25 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 26 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 27 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 28 * OF THIS SOFTWARE. 29 ****************************************************************************** 30 * 31 * $Log: tiffset.c,v $ 32 * Revision 1.13 2008-01-01 15:46:28 fwarmerdam 33 * Changes to reflect the fact that TIFFFieldWithTag() and TIFFFieldWithName() 34 * now return TIFFField pointers instead of TIFFFieldInfo pointers. 35 * 36 * Revision 1.12 2007/02/24 17:14:14 dron 37 * Properly handle tags with TIFF_VARIABLE writecount. As per bug 38 * http://bugzilla.remotesensing.org/show_bug.cgi?id=1350 39 * 40 * Revision 1.11 2005/09/13 14:13:42 dron 41 * Avoid warnings. 42 * 43 * Revision 1.10 2005/02/24 14:47:11 fwarmerdam 44 * Updated header. 45 * 46 */ 47 48 49 #include <stdio.h> 50 #include <string.h> 51 #include <stdlib.h> 52 53 #include "tiffio.h" 54 #include "tif_dir.h" 55 56 static char* usageMsg[] = { 57 "usage: tiffset [options] filename", 58 "where options are:", 59 " -s <tagname> [count] <value>... set the tag value", 60 " -sf <tagname> <filename> read the tag value from file (for ASCII tags only)", 61 NULL 62 }; 63 64 static void 65 usage(void) 66 { 67 int i; 68 for (i = 0; usageMsg[i]; i++) 69 fprintf(stderr, "%s\n", usageMsg[i]); 70 exit(-1); 71 } 72 73 static const TIFFField * 74 GetField(TIFF *tiff, const char *tagname) 75 { 76 const TIFFField *fip; 77 78 if( atoi(tagname) > 0 ) 79 fip = TIFFFieldWithTag(tiff, (ttag_t)atoi(tagname)); 80 else 81 fip = TIFFFieldWithName(tiff, tagname); 82 83 if (!fip) { 84 fprintf( stderr, "Field name %s not recognised.\n", tagname ); 85 return (TIFFField *)NULL; 86 } 87 88 return fip; 89 } 90 91 int 92 main(int argc, char* argv[]) 93 { 94 TIFF *tiff; 95 int arg_index; 96 97 if (argc < 2) 98 usage(); 99 100 tiff = TIFFOpen(argv[argc-1], "r+"); 101 if (tiff == NULL) 102 return 2; 103 104 for( arg_index = 1; arg_index < argc-1; arg_index++ ) { 105 if (strcmp(argv[arg_index],"-s") == 0 && arg_index < argc-3) { 106 const TIFFField *fip; 107 const char *tagname; 108 109 arg_index++; 110 tagname = argv[arg_index]; 111 fip = GetField(tiff, tagname); 112 113 if (!fip) 114 return 3; 115 116 arg_index++; 117 if (fip->field_type == TIFF_ASCII) { 118 if (TIFFSetField(tiff, fip->field_tag, argv[arg_index]) != 1) 119 fprintf( stderr, "Failed to set %s=%s\n", 120 fip->field_name, argv[arg_index] ); 121 } else if (fip->field_writecount > 0 122 || fip->field_writecount == TIFF_VARIABLE) { 123 int ret = 1; 124 short wc; 125 126 if (fip->field_writecount == TIFF_VARIABLE) 127 wc = atoi(argv[arg_index++]); 128 else 129 wc = fip->field_writecount; 130 131 if (argc - arg_index < wc) { 132 fprintf( stderr, 133 "Number of tag values is not enough. " 134 "Expected %d values for %s tag, got %d\n", 135 wc, fip->field_name, argc - arg_index); 136 return 4; 137 } 138 139 if (wc > 1) { 140 int i, size; 141 void *array; 142 143 switch (fip->field_type) { 144 /* 145 * XXX: We can't use TIFFDataWidth() 146 * to determine the space needed to store 147 * the value. For TIFF_RATIONAL values 148 * TIFFDataWidth() returns 8, but we use 4-byte 149 * float to represent rationals. 150 */ 151 case TIFF_BYTE: 152 case TIFF_ASCII: 153 case TIFF_SBYTE: 154 case TIFF_UNDEFINED: 155 default: 156 size = 1; 157 break; 158 159 case TIFF_SHORT: 160 case TIFF_SSHORT: 161 size = 2; 162 break; 163 164 case TIFF_LONG: 165 case TIFF_SLONG: 166 case TIFF_FLOAT: 167 case TIFF_IFD: 168 case TIFF_RATIONAL: 169 case TIFF_SRATIONAL: 170 size = 4; 171 break; 172 173 case TIFF_DOUBLE: 174 size = 8; 175 break; 176 } 177 178 array = _TIFFmalloc(wc * size); 179 if (!array) { 180 fprintf(stderr, "No space for %s tag\n", 181 tagname); 182 return 4; 183 } 184 185 switch (fip->field_type) { 186 case TIFF_BYTE: 187 for (i = 0; i < wc; i++) 188 ((uint8 *)array)[i] = atoi(argv[arg_index+i]); 189 break; 190 case TIFF_SHORT: 191 for (i = 0; i < wc; i++) 192 ((uint16 *)array)[i] = atoi(argv[arg_index+i]); 193 break; 194 case TIFF_SBYTE: 195 for (i = 0; i < wc; i++) 196 ((int8 *)array)[i] = atoi(argv[arg_index+i]); 197 break; 198 case TIFF_SSHORT: 199 for (i = 0; i < wc; i++) 200 ((int16 *)array)[i] = atoi(argv[arg_index+i]); 201 break; 202 case TIFF_LONG: 203 for (i = 0; i < wc; i++) 204 ((uint32 *)array)[i] = atol(argv[arg_index+i]); 205 break; 206 case TIFF_SLONG: 207 case TIFF_IFD: 208 for (i = 0; i < wc; i++) 209 ((uint32 *)array)[i] = atol(argv[arg_index+i]); 210 break; 211 case TIFF_DOUBLE: 212 for (i = 0; i < wc; i++) 213 ((double *)array)[i] = atof(argv[arg_index+i]); 214 break; 215 case TIFF_RATIONAL: 216 case TIFF_SRATIONAL: 217 case TIFF_FLOAT: 218 for (i = 0; i < wc; i++) 219 ((float *)array)[i] = (float)atof(argv[arg_index+i]); 220 break; 221 default: 222 break; 223 } 224 225 if (fip->field_passcount) { 226 ret = TIFFSetField(tiff, fip->field_tag, 227 wc, array); 228 } else { 229 ret = TIFFSetField(tiff, fip->field_tag, 230 array); 231 } 232 233 _TIFFfree(array); 234 } else { 235 switch (fip->field_type) { 236 case TIFF_BYTE: 237 case TIFF_SHORT: 238 case TIFF_SBYTE: 239 case TIFF_SSHORT: 240 ret = TIFFSetField(tiff, fip->field_tag, 241 atoi(argv[arg_index++])); 242 break; 243 case TIFF_LONG: 244 case TIFF_SLONG: 245 case TIFF_IFD: 246 ret = TIFFSetField(tiff, fip->field_tag, 247 atol(argv[arg_index++])); 248 break; 249 case TIFF_DOUBLE: 250 ret = TIFFSetField(tiff, fip->field_tag, 251 atof(argv[arg_index++])); 252 break; 253 case TIFF_RATIONAL: 254 case TIFF_SRATIONAL: 255 case TIFF_FLOAT: 256 ret = TIFFSetField(tiff, fip->field_tag, 257 (float)atof(argv[arg_index++])); 258 break; 259 default: 260 break; 261 } 262 } 263 264 if (ret != 1) 265 fprintf(stderr, "Failed to set %s\n", fip->field_name); 266 arg_index += wc; 267 } 268 } else if (strcmp(argv[arg_index],"-sf") == 0 && arg_index < argc-3) { 269 FILE *fp; 270 const TIFFField *fip; 271 char *text; 272 size_t len; 273 274 arg_index++; 275 fip = GetField(tiff, argv[arg_index]); 276 277 if (!fip) 278 return 3; 279 280 if (fip->field_type != TIFF_ASCII) { 281 fprintf( stderr, 282 "Only ASCII tags can be set from file. " 283 "%s is not ASCII tag.\n", fip->field_name ); 284 return 5; 285 } 286 287 arg_index++; 288 fp = fopen( argv[arg_index], "rt" ); 289 if(fp == NULL) { 290 perror( argv[arg_index] ); 291 continue; 292 } 293 294 text = (char *) malloc(1000000); 295 len = fread( text, 1, 999999, fp ); 296 text[len] = '\0'; 297 298 fclose( fp ); 299 300 if(TIFFSetField( tiff, fip->field_tag, text ) != 1) { 301 fprintf(stderr, "Failed to set %s from file %s\n", 302 fip->field_name, argv[arg_index]); 303 } 304 305 _TIFFfree( text ); 306 arg_index++; 307 } else { 308 fprintf(stderr, "Unrecognised option: %s\n", 309 argv[arg_index]); 310 usage(); 311 } 312 } 313 314 TIFFRewriteDirectory(tiff); 315 TIFFClose(tiff); 316 return 0; 317 } 318 319 /* vim: set ts=8 sts=8 sw=8 noet: */ 320