xref: /libtiff-4.0.7/tools/tiffset.c (revision a042a8d4)
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