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