]>
Commit | Line | Data |
---|---|---|
8414a40c | 1 | /****************************************************************************** |
8414a40c VZ |
2 | * |
3 | * Project: libtiff tools | |
4 | * Purpose: Mainline for setting metadata in existing TIFF files. | |
5 | * Author: Frank Warmerdam, warmerdam@pobox.com | |
6 | * | |
7 | ****************************************************************************** | |
8 | * Copyright (c) 2000, Frank Warmerdam | |
9 | * | |
10 | * Permission to use, copy, modify, distribute, and sell this software and | |
11 | * its documentation for any purpose is hereby granted without fee, provided | |
12 | * that (i) the above copyright notices and this permission notice appear in | |
13 | * all copies of the software and related documentation, and (ii) the names of | |
14 | * Sam Leffler and Silicon Graphics may not be used in any advertising or | |
15 | * publicity relating to the software without the specific, prior written | |
16 | * permission of Sam Leffler and Silicon Graphics. | |
17 | * | |
18 | * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, | |
19 | * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY | |
20 | * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. | |
21 | * | |
22 | * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR | |
23 | * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, | |
24 | * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, | |
25 | * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF | |
26 | * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | |
27 | * OF THIS SOFTWARE. | |
28 | ****************************************************************************** | |
8414a40c VZ |
29 | */ |
30 | ||
31 | ||
32 | #include <stdio.h> | |
33 | #include <string.h> | |
34 | #include <stdlib.h> | |
35 | ||
36 | #include "tiffio.h" | |
37 | ||
38 | static char* usageMsg[] = { | |
39 | "usage: tiffset [options] filename", | |
40 | "where options are:", | |
41 | " -s <tagname> [count] <value>... set the tag value", | |
80ed523f VZ |
42 | " -d <dirno> set the directory", |
43 | " -sd <diroff> set the subdirectory", | |
8414a40c VZ |
44 | " -sf <tagname> <filename> read the tag value from file (for ASCII tags only)", |
45 | NULL | |
46 | }; | |
47 | ||
48 | static void | |
49 | usage(void) | |
50 | { | |
51 | int i; | |
52 | for (i = 0; usageMsg[i]; i++) | |
53 | fprintf(stderr, "%s\n", usageMsg[i]); | |
54 | exit(-1); | |
55 | } | |
56 | ||
80ed523f | 57 | static const TIFFField * |
8414a40c VZ |
58 | GetField(TIFF *tiff, const char *tagname) |
59 | { | |
80ed523f | 60 | const TIFFField *fip; |
8414a40c VZ |
61 | |
62 | if( atoi(tagname) > 0 ) | |
63 | fip = TIFFFieldWithTag(tiff, (ttag_t)atoi(tagname)); | |
64 | else | |
65 | fip = TIFFFieldWithName(tiff, tagname); | |
66 | ||
67 | if (!fip) { | |
80ed523f VZ |
68 | fprintf( stderr, "Field name \"%s\" is not recognised.\n", tagname ); |
69 | return (TIFFField *)NULL; | |
8414a40c VZ |
70 | } |
71 | ||
72 | return fip; | |
73 | } | |
74 | ||
75 | int | |
76 | main(int argc, char* argv[]) | |
77 | { | |
78 | TIFF *tiff; | |
79 | int arg_index; | |
80 | ||
81 | if (argc < 2) | |
82 | usage(); | |
83 | ||
84 | tiff = TIFFOpen(argv[argc-1], "r+"); | |
85 | if (tiff == NULL) | |
86 | return 2; | |
87 | ||
88 | for( arg_index = 1; arg_index < argc-1; arg_index++ ) { | |
80ed523f VZ |
89 | if (strcmp(argv[arg_index],"-d") == 0 && arg_index < argc-2) { |
90 | arg_index++; | |
91 | if( TIFFSetDirectory(tiff, atoi(argv[arg_index]) ) != 1 ) | |
92 | { | |
93 | fprintf( stderr, "Failed to set directory=%s\n", argv[arg_index] ); | |
94 | return 6; | |
95 | } | |
96 | arg_index++; | |
97 | } | |
98 | if (strcmp(argv[arg_index],"-sd") == 0 && arg_index < argc-2) { | |
99 | arg_index++; | |
100 | if( TIFFSetSubDirectory(tiff, atoi(argv[arg_index]) ) != 1 ) | |
101 | { | |
102 | fprintf( stderr, "Failed to set sub directory=%s\n", argv[arg_index] ); | |
103 | return 7; | |
104 | } | |
105 | arg_index++; | |
106 | } | |
8414a40c | 107 | if (strcmp(argv[arg_index],"-s") == 0 && arg_index < argc-3) { |
80ed523f | 108 | const TIFFField *fip; |
8414a40c VZ |
109 | const char *tagname; |
110 | ||
111 | arg_index++; | |
112 | tagname = argv[arg_index]; | |
113 | fip = GetField(tiff, tagname); | |
114 | ||
115 | if (!fip) | |
116 | return 3; | |
117 | ||
118 | arg_index++; | |
80ed523f VZ |
119 | if (TIFFFieldDataType(fip) == TIFF_ASCII) { |
120 | if (TIFFSetField(tiff, TIFFFieldTag(fip), argv[arg_index]) != 1) | |
8414a40c | 121 | fprintf( stderr, "Failed to set %s=%s\n", |
80ed523f VZ |
122 | TIFFFieldName(fip), argv[arg_index] ); |
123 | } else if (TIFFFieldWriteCount(fip) > 0 | |
124 | || TIFFFieldWriteCount(fip) == TIFF_VARIABLE) { | |
8414a40c VZ |
125 | int ret = 1; |
126 | short wc; | |
127 | ||
80ed523f | 128 | if (TIFFFieldWriteCount(fip) == TIFF_VARIABLE) |
8414a40c VZ |
129 | wc = atoi(argv[arg_index++]); |
130 | else | |
80ed523f | 131 | wc = TIFFFieldWriteCount(fip); |
8414a40c VZ |
132 | |
133 | if (argc - arg_index < wc) { | |
134 | fprintf( stderr, | |
135 | "Number of tag values is not enough. " | |
136 | "Expected %d values for %s tag, got %d\n", | |
80ed523f | 137 | wc, TIFFFieldName(fip), argc - arg_index); |
8414a40c VZ |
138 | return 4; |
139 | } | |
140 | ||
141 | if (wc > 1) { | |
142 | int i, size; | |
143 | void *array; | |
144 | ||
80ed523f | 145 | switch (TIFFFieldDataType(fip)) { |
8414a40c VZ |
146 | /* |
147 | * XXX: We can't use TIFFDataWidth() | |
148 | * to determine the space needed to store | |
149 | * the value. For TIFF_RATIONAL values | |
150 | * TIFFDataWidth() returns 8, but we use 4-byte | |
151 | * float to represent rationals. | |
152 | */ | |
153 | case TIFF_BYTE: | |
154 | case TIFF_ASCII: | |
155 | case TIFF_SBYTE: | |
156 | case TIFF_UNDEFINED: | |
157 | default: | |
158 | size = 1; | |
159 | break; | |
160 | ||
161 | case TIFF_SHORT: | |
162 | case TIFF_SSHORT: | |
163 | size = 2; | |
164 | break; | |
165 | ||
166 | case TIFF_LONG: | |
167 | case TIFF_SLONG: | |
168 | case TIFF_FLOAT: | |
169 | case TIFF_IFD: | |
170 | case TIFF_RATIONAL: | |
171 | case TIFF_SRATIONAL: | |
172 | size = 4; | |
173 | break; | |
174 | ||
175 | case TIFF_DOUBLE: | |
176 | size = 8; | |
177 | break; | |
178 | } | |
179 | ||
180 | array = _TIFFmalloc(wc * size); | |
181 | if (!array) { | |
182 | fprintf(stderr, "No space for %s tag\n", | |
183 | tagname); | |
184 | return 4; | |
185 | } | |
186 | ||
80ed523f | 187 | switch (TIFFFieldDataType(fip)) { |
8414a40c VZ |
188 | case TIFF_BYTE: |
189 | for (i = 0; i < wc; i++) | |
190 | ((uint8 *)array)[i] = atoi(argv[arg_index+i]); | |
191 | break; | |
192 | case TIFF_SHORT: | |
193 | for (i = 0; i < wc; i++) | |
194 | ((uint16 *)array)[i] = atoi(argv[arg_index+i]); | |
195 | break; | |
196 | case TIFF_SBYTE: | |
197 | for (i = 0; i < wc; i++) | |
198 | ((int8 *)array)[i] = atoi(argv[arg_index+i]); | |
199 | break; | |
200 | case TIFF_SSHORT: | |
201 | for (i = 0; i < wc; i++) | |
202 | ((int16 *)array)[i] = atoi(argv[arg_index+i]); | |
203 | break; | |
204 | case TIFF_LONG: | |
205 | for (i = 0; i < wc; i++) | |
206 | ((uint32 *)array)[i] = atol(argv[arg_index+i]); | |
207 | break; | |
208 | case TIFF_SLONG: | |
209 | case TIFF_IFD: | |
210 | for (i = 0; i < wc; i++) | |
211 | ((uint32 *)array)[i] = atol(argv[arg_index+i]); | |
212 | break; | |
213 | case TIFF_DOUBLE: | |
214 | for (i = 0; i < wc; i++) | |
215 | ((double *)array)[i] = atof(argv[arg_index+i]); | |
216 | break; | |
217 | case TIFF_RATIONAL: | |
218 | case TIFF_SRATIONAL: | |
219 | case TIFF_FLOAT: | |
220 | for (i = 0; i < wc; i++) | |
221 | ((float *)array)[i] = (float)atof(argv[arg_index+i]); | |
222 | break; | |
223 | default: | |
224 | break; | |
225 | } | |
226 | ||
80ed523f VZ |
227 | if (TIFFFieldPassCount(fip)) { |
228 | ret = TIFFSetField(tiff, TIFFFieldTag(fip), | |
8414a40c | 229 | wc, array); |
80ed523f VZ |
230 | } else if (TIFFFieldTag(fip) == TIFFTAG_PAGENUMBER |
231 | || TIFFFieldTag(fip) == TIFFTAG_HALFTONEHINTS | |
232 | || TIFFFieldTag(fip) == TIFFTAG_YCBCRSUBSAMPLING | |
233 | || TIFFFieldTag(fip) == TIFFTAG_DOTRANGE) { | |
234 | if (TIFFFieldDataType(fip) == TIFF_BYTE) { | |
235 | ret = TIFFSetField(tiff, TIFFFieldTag(fip), | |
236 | ((uint8 *)array)[0], ((uint8 *)array)[1]); | |
237 | } else if (TIFFFieldDataType(fip) == TIFF_SHORT) { | |
238 | ret = TIFFSetField(tiff, TIFFFieldTag(fip), | |
239 | ((uint16 *)array)[0], ((uint16 *)array)[1]); | |
240 | } | |
241 | } else { | |
242 | ret = TIFFSetField(tiff, TIFFFieldTag(fip), | |
8414a40c VZ |
243 | array); |
244 | } | |
245 | ||
246 | _TIFFfree(array); | |
247 | } else { | |
80ed523f | 248 | switch (TIFFFieldDataType(fip)) { |
8414a40c VZ |
249 | case TIFF_BYTE: |
250 | case TIFF_SHORT: | |
251 | case TIFF_SBYTE: | |
252 | case TIFF_SSHORT: | |
80ed523f | 253 | ret = TIFFSetField(tiff, TIFFFieldTag(fip), |
8414a40c VZ |
254 | atoi(argv[arg_index++])); |
255 | break; | |
256 | case TIFF_LONG: | |
257 | case TIFF_SLONG: | |
258 | case TIFF_IFD: | |
80ed523f | 259 | ret = TIFFSetField(tiff, TIFFFieldTag(fip), |
8414a40c VZ |
260 | atol(argv[arg_index++])); |
261 | break; | |
262 | case TIFF_DOUBLE: | |
80ed523f | 263 | ret = TIFFSetField(tiff, TIFFFieldTag(fip), |
8414a40c VZ |
264 | atof(argv[arg_index++])); |
265 | break; | |
266 | case TIFF_RATIONAL: | |
267 | case TIFF_SRATIONAL: | |
268 | case TIFF_FLOAT: | |
80ed523f | 269 | ret = TIFFSetField(tiff, TIFFFieldTag(fip), |
8414a40c VZ |
270 | (float)atof(argv[arg_index++])); |
271 | break; | |
272 | default: | |
273 | break; | |
274 | } | |
275 | } | |
276 | ||
277 | if (ret != 1) | |
80ed523f | 278 | fprintf(stderr, "Failed to set %s\n", TIFFFieldName(fip)); |
8414a40c VZ |
279 | arg_index += wc; |
280 | } | |
281 | } else if (strcmp(argv[arg_index],"-sf") == 0 && arg_index < argc-3) { | |
282 | FILE *fp; | |
80ed523f | 283 | const TIFFField *fip; |
8414a40c | 284 | char *text; |
80ed523f | 285 | size_t len; |
8414a40c VZ |
286 | |
287 | arg_index++; | |
288 | fip = GetField(tiff, argv[arg_index]); | |
289 | ||
290 | if (!fip) | |
291 | return 3; | |
292 | ||
80ed523f | 293 | if (TIFFFieldDataType(fip) != TIFF_ASCII) { |
8414a40c VZ |
294 | fprintf( stderr, |
295 | "Only ASCII tags can be set from file. " | |
80ed523f | 296 | "%s is not ASCII tag.\n", TIFFFieldName(fip) ); |
8414a40c VZ |
297 | return 5; |
298 | } | |
299 | ||
300 | arg_index++; | |
301 | fp = fopen( argv[arg_index], "rt" ); | |
302 | if(fp == NULL) { | |
303 | perror( argv[arg_index] ); | |
304 | continue; | |
305 | } | |
306 | ||
307 | text = (char *) malloc(1000000); | |
308 | len = fread( text, 1, 999999, fp ); | |
309 | text[len] = '\0'; | |
310 | ||
311 | fclose( fp ); | |
312 | ||
80ed523f | 313 | if(TIFFSetField( tiff, TIFFFieldTag(fip), text ) != 1) { |
8414a40c | 314 | fprintf(stderr, "Failed to set %s from file %s\n", |
80ed523f | 315 | TIFFFieldName(fip), argv[arg_index]); |
8414a40c VZ |
316 | } |
317 | ||
318 | _TIFFfree( text ); | |
319 | arg_index++; | |
320 | } else { | |
321 | fprintf(stderr, "Unrecognised option: %s\n", | |
322 | argv[arg_index]); | |
323 | usage(); | |
324 | } | |
325 | } | |
326 | ||
327 | TIFFRewriteDirectory(tiff); | |
328 | TIFFClose(tiff); | |
329 | return 0; | |
330 | } | |
331 | ||
332 | /* vim: set ts=8 sts=8 sw=8 noet: */ | |
80ed523f VZ |
333 | /* |
334 | * Local Variables: | |
335 | * mode: c | |
336 | * c-basic-offset: 8 | |
337 | * fill-column: 78 | |
338 | * End: | |
339 | */ |