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