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