1 /****************************************************************************** 2 * $Id: tiffset.c,v 1.14 2010-03-10 18:56:50 bfriesen 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.14 2010-03-10 18:56:50 bfriesen 33 * * libtiff/tif_aux.c (_TIFFCheckRealloc): Improve error message so 34 * that it is clearly a memory allocation error message, and also 35 * includes the size of the allocation request. 36 * 37 * Revision 1.13 2008/01/01 15:46:28 fwarmerdam 38 * Changes to reflect the fact that TIFFFieldWithTag() and TIFFFieldWithName() 39 * now return TIFFField pointers instead of TIFFFieldInfo pointers. 40 * 41 * Revision 1.12 2007/02/24 17:14:14 dron 42 * Properly handle tags with TIFF_VARIABLE writecount. As per bug 43 * http://bugzilla.remotesensing.org/show_bug.cgi?id=1350 44 * 45 * Revision 1.11 2005/09/13 14:13:42 dron 46 * Avoid warnings. 47 * 48 * Revision 1.10 2005/02/24 14:47:11 fwarmerdam 49 * Updated header. 50 * 51 */ 52 53 54 #include <stdio.h> 55 #include <string.h> 56 #include <stdlib.h> 57 58 #include "tiffio.h" 59 #include "tif_dir.h" 60 61 static char* usageMsg[] = { 62 "usage: tiffset [options] filename", 63 "where options are:", 64 " -s <tagname> [count] <value>... set the tag value", 65 " -sf <tagname> <filename> read the tag value from file (for ASCII tags only)", 66 NULL 67 }; 68 69 static void 70 usage(void) 71 { 72 int i; 73 for (i = 0; usageMsg[i]; i++) 74 fprintf(stderr, "%s\n", usageMsg[i]); 75 exit(-1); 76 } 77 78 static const TIFFField * 79 GetField(TIFF *tiff, const char *tagname) 80 { 81 const TIFFField *fip; 82 83 if( atoi(tagname) > 0 ) 84 fip = TIFFFieldWithTag(tiff, (ttag_t)atoi(tagname)); 85 else 86 fip = TIFFFieldWithName(tiff, tagname); 87 88 if (!fip) { 89 fprintf( stderr, "Field name %s not recognised.\n", tagname ); 90 return (TIFFField *)NULL; 91 } 92 93 return fip; 94 } 95 96 int 97 main(int argc, char* argv[]) 98 { 99 TIFF *tiff; 100 int arg_index; 101 102 if (argc < 2) 103 usage(); 104 105 tiff = TIFFOpen(argv[argc-1], "r+"); 106 if (tiff == NULL) 107 return 2; 108 109 for( arg_index = 1; arg_index < argc-1; arg_index++ ) { 110 if (strcmp(argv[arg_index],"-s") == 0 && arg_index < argc-3) { 111 const TIFFField *fip; 112 const char *tagname; 113 114 arg_index++; 115 tagname = argv[arg_index]; 116 fip = GetField(tiff, tagname); 117 118 if (!fip) 119 return 3; 120 121 arg_index++; 122 if (fip->field_type == TIFF_ASCII) { 123 if (TIFFSetField(tiff, fip->field_tag, argv[arg_index]) != 1) 124 fprintf( stderr, "Failed to set %s=%s\n", 125 fip->field_name, argv[arg_index] ); 126 } else if (fip->field_writecount > 0 127 || fip->field_writecount == TIFF_VARIABLE) { 128 int ret = 1; 129 short wc; 130 131 if (fip->field_writecount == TIFF_VARIABLE) 132 wc = atoi(argv[arg_index++]); 133 else 134 wc = fip->field_writecount; 135 136 if (argc - arg_index < wc) { 137 fprintf( stderr, 138 "Number of tag values is not enough. " 139 "Expected %d values for %s tag, got %d\n", 140 wc, fip->field_name, argc - arg_index); 141 return 4; 142 } 143 144 if (wc > 1) { 145 int i, size; 146 void *array; 147 148 switch (fip->field_type) { 149 /* 150 * XXX: We can't use TIFFDataWidth() 151 * to determine the space needed to store 152 * the value. For TIFF_RATIONAL values 153 * TIFFDataWidth() returns 8, but we use 4-byte 154 * float to represent rationals. 155 */ 156 case TIFF_BYTE: 157 case TIFF_ASCII: 158 case TIFF_SBYTE: 159 case TIFF_UNDEFINED: 160 default: 161 size = 1; 162 break; 163 164 case TIFF_SHORT: 165 case TIFF_SSHORT: 166 size = 2; 167 break; 168 169 case TIFF_LONG: 170 case TIFF_SLONG: 171 case TIFF_FLOAT: 172 case TIFF_IFD: 173 case TIFF_RATIONAL: 174 case TIFF_SRATIONAL: 175 size = 4; 176 break; 177 178 case TIFF_DOUBLE: 179 size = 8; 180 break; 181 } 182 183 array = _TIFFmalloc(wc * size); 184 if (!array) { 185 fprintf(stderr, "No space for %s tag\n", 186 tagname); 187 return 4; 188 } 189 190 switch (fip->field_type) { 191 case TIFF_BYTE: 192 for (i = 0; i < wc; i++) 193 ((uint8 *)array)[i] = atoi(argv[arg_index+i]); 194 break; 195 case TIFF_SHORT: 196 for (i = 0; i < wc; i++) 197 ((uint16 *)array)[i] = atoi(argv[arg_index+i]); 198 break; 199 case TIFF_SBYTE: 200 for (i = 0; i < wc; i++) 201 ((int8 *)array)[i] = atoi(argv[arg_index+i]); 202 break; 203 case TIFF_SSHORT: 204 for (i = 0; i < wc; i++) 205 ((int16 *)array)[i] = atoi(argv[arg_index+i]); 206 break; 207 case TIFF_LONG: 208 for (i = 0; i < wc; i++) 209 ((uint32 *)array)[i] = atol(argv[arg_index+i]); 210 break; 211 case TIFF_SLONG: 212 case TIFF_IFD: 213 for (i = 0; i < wc; i++) 214 ((uint32 *)array)[i] = atol(argv[arg_index+i]); 215 break; 216 case TIFF_DOUBLE: 217 for (i = 0; i < wc; i++) 218 ((double *)array)[i] = atof(argv[arg_index+i]); 219 break; 220 case TIFF_RATIONAL: 221 case TIFF_SRATIONAL: 222 case TIFF_FLOAT: 223 for (i = 0; i < wc; i++) 224 ((float *)array)[i] = (float)atof(argv[arg_index+i]); 225 break; 226 default: 227 break; 228 } 229 230 if (fip->field_passcount) { 231 ret = TIFFSetField(tiff, fip->field_tag, 232 wc, array); 233 } else { 234 ret = TIFFSetField(tiff, fip->field_tag, 235 array); 236 } 237 238 _TIFFfree(array); 239 } else { 240 switch (fip->field_type) { 241 case TIFF_BYTE: 242 case TIFF_SHORT: 243 case TIFF_SBYTE: 244 case TIFF_SSHORT: 245 ret = TIFFSetField(tiff, fip->field_tag, 246 atoi(argv[arg_index++])); 247 break; 248 case TIFF_LONG: 249 case TIFF_SLONG: 250 case TIFF_IFD: 251 ret = TIFFSetField(tiff, fip->field_tag, 252 atol(argv[arg_index++])); 253 break; 254 case TIFF_DOUBLE: 255 ret = TIFFSetField(tiff, fip->field_tag, 256 atof(argv[arg_index++])); 257 break; 258 case TIFF_RATIONAL: 259 case TIFF_SRATIONAL: 260 case TIFF_FLOAT: 261 ret = TIFFSetField(tiff, fip->field_tag, 262 (float)atof(argv[arg_index++])); 263 break; 264 default: 265 break; 266 } 267 } 268 269 if (ret != 1) 270 fprintf(stderr, "Failed to set %s\n", fip->field_name); 271 arg_index += wc; 272 } 273 } else if (strcmp(argv[arg_index],"-sf") == 0 && arg_index < argc-3) { 274 FILE *fp; 275 const TIFFField *fip; 276 char *text; 277 size_t len; 278 279 arg_index++; 280 fip = GetField(tiff, argv[arg_index]); 281 282 if (!fip) 283 return 3; 284 285 if (fip->field_type != TIFF_ASCII) { 286 fprintf( stderr, 287 "Only ASCII tags can be set from file. " 288 "%s is not ASCII tag.\n", fip->field_name ); 289 return 5; 290 } 291 292 arg_index++; 293 fp = fopen( argv[arg_index], "rt" ); 294 if(fp == NULL) { 295 perror( argv[arg_index] ); 296 continue; 297 } 298 299 text = (char *) malloc(1000000); 300 len = fread( text, 1, 999999, fp ); 301 text[len] = '\0'; 302 303 fclose( fp ); 304 305 if(TIFFSetField( tiff, fip->field_tag, text ) != 1) { 306 fprintf(stderr, "Failed to set %s from file %s\n", 307 fip->field_name, argv[arg_index]); 308 } 309 310 _TIFFfree( text ); 311 arg_index++; 312 } else { 313 fprintf(stderr, "Unrecognised option: %s\n", 314 argv[arg_index]); 315 usage(); 316 } 317 } 318 319 TIFFRewriteDirectory(tiff); 320 TIFFClose(tiff); 321 return 0; 322 } 323 324 /* vim: set ts=8 sts=8 sw=8 noet: */ 325 /* 326 * Local Variables: 327 * mode: c 328 * c-basic-offset: 8 329 * fill-column: 78 330 * End: 331 */ 332