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