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