]>
Commit | Line | Data |
---|---|---|
8414a40c VZ |
1 | /****************************************************************************** |
2 | * $Id$ | |
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 | ****************************************************************************** | |
8414a40c VZ |
30 | */ |
31 | ||
32 | ||
33 | #include <stdio.h> | |
34 | #include <string.h> | |
35 | #include <stdlib.h> | |
36 | ||
37 | #include "tiffio.h" | |
38 | ||
39 | static char* usageMsg[] = { | |
40 | "usage: tiffset [options] filename", | |
41 | "where options are:", | |
42 | " -s <tagname> [count] <value>... set the tag value", | |
80ed523f VZ |
43 | " -d <dirno> set the directory", |
44 | " -sd <diroff> set the subdirectory", | |
8414a40c VZ |
45 | " -sf <tagname> <filename> read the tag value from file (for ASCII tags only)", |
46 | NULL | |
47 | }; | |
48 | ||
49 | static void | |
50 | usage(void) | |
51 | { | |
52 | int i; | |
53 | for (i = 0; usageMsg[i]; i++) | |
54 | fprintf(stderr, "%s\n", usageMsg[i]); | |
55 | exit(-1); | |
56 | } | |
57 | ||
80ed523f | 58 | static const TIFFField * |
8414a40c VZ |
59 | GetField(TIFF *tiff, const char *tagname) |
60 | { | |
80ed523f | 61 | const TIFFField *fip; |
8414a40c VZ |
62 | |
63 | if( atoi(tagname) > 0 ) | |
64 | fip = TIFFFieldWithTag(tiff, (ttag_t)atoi(tagname)); | |
65 | else | |
66 | fip = TIFFFieldWithName(tiff, tagname); | |
67 | ||
68 | if (!fip) { | |
80ed523f VZ |
69 | fprintf( stderr, "Field name \"%s\" is not recognised.\n", tagname ); |
70 | return (TIFFField *)NULL; | |
8414a40c VZ |
71 | } |
72 | ||
73 | return fip; | |
74 | } | |
75 | ||
76 | int | |
77 | main(int argc, char* argv[]) | |
78 | { | |
79 | TIFF *tiff; | |
80 | int arg_index; | |
81 | ||
82 | if (argc < 2) | |
83 | usage(); | |
84 | ||
85 | tiff = TIFFOpen(argv[argc-1], "r+"); | |
86 | if (tiff == NULL) | |
87 | return 2; | |
88 | ||
89 | for( arg_index = 1; arg_index < argc-1; arg_index++ ) { | |
80ed523f VZ |
90 | if (strcmp(argv[arg_index],"-d") == 0 && arg_index < argc-2) { |
91 | arg_index++; | |
92 | if( TIFFSetDirectory(tiff, atoi(argv[arg_index]) ) != 1 ) | |
93 | { | |
94 | fprintf( stderr, "Failed to set directory=%s\n", argv[arg_index] ); | |
95 | return 6; | |
96 | } | |
97 | arg_index++; | |
98 | } | |
99 | if (strcmp(argv[arg_index],"-sd") == 0 && arg_index < argc-2) { | |
100 | arg_index++; | |
101 | if( TIFFSetSubDirectory(tiff, atoi(argv[arg_index]) ) != 1 ) | |
102 | { | |
103 | fprintf( stderr, "Failed to set sub directory=%s\n", argv[arg_index] ); | |
104 | return 7; | |
105 | } | |
106 | arg_index++; | |
107 | } | |
8414a40c | 108 | if (strcmp(argv[arg_index],"-s") == 0 && arg_index < argc-3) { |
80ed523f | 109 | const TIFFField *fip; |
8414a40c VZ |
110 | const char *tagname; |
111 | ||
112 | arg_index++; | |
113 | tagname = argv[arg_index]; | |
114 | fip = GetField(tiff, tagname); | |
115 | ||
116 | if (!fip) | |
117 | return 3; | |
118 | ||
119 | arg_index++; | |
80ed523f VZ |
120 | if (TIFFFieldDataType(fip) == TIFF_ASCII) { |
121 | if (TIFFSetField(tiff, TIFFFieldTag(fip), argv[arg_index]) != 1) | |
8414a40c | 122 | fprintf( stderr, "Failed to set %s=%s\n", |
80ed523f VZ |
123 | TIFFFieldName(fip), argv[arg_index] ); |
124 | } else if (TIFFFieldWriteCount(fip) > 0 | |
125 | || TIFFFieldWriteCount(fip) == TIFF_VARIABLE) { | |
8414a40c VZ |
126 | int ret = 1; |
127 | short wc; | |
128 | ||
80ed523f | 129 | if (TIFFFieldWriteCount(fip) == TIFF_VARIABLE) |
8414a40c VZ |
130 | wc = atoi(argv[arg_index++]); |
131 | else | |
80ed523f | 132 | wc = TIFFFieldWriteCount(fip); |
8414a40c VZ |
133 | |
134 | if (argc - arg_index < wc) { | |
135 | fprintf( stderr, | |
136 | "Number of tag values is not enough. " | |
137 | "Expected %d values for %s tag, got %d\n", | |
80ed523f | 138 | wc, TIFFFieldName(fip), argc - arg_index); |
8414a40c VZ |
139 | return 4; |
140 | } | |
141 | ||
142 | if (wc > 1) { | |
143 | int i, size; | |
144 | void *array; | |
145 | ||
80ed523f | 146 | switch (TIFFFieldDataType(fip)) { |
8414a40c VZ |
147 | /* |
148 | * XXX: We can't use TIFFDataWidth() | |
149 | * to determine the space needed to store | |
150 | * the value. For TIFF_RATIONAL values | |
151 | * TIFFDataWidth() returns 8, but we use 4-byte | |
152 | * float to represent rationals. | |
153 | */ | |
154 | case TIFF_BYTE: | |
155 | case TIFF_ASCII: | |
156 | case TIFF_SBYTE: | |
157 | case TIFF_UNDEFINED: | |
158 | default: | |
159 | size = 1; | |
160 | break; | |
161 | ||
162 | case TIFF_SHORT: | |
163 | case TIFF_SSHORT: | |
164 | size = 2; | |
165 | break; | |
166 | ||
167 | case TIFF_LONG: | |
168 | case TIFF_SLONG: | |
169 | case TIFF_FLOAT: | |
170 | case TIFF_IFD: | |
171 | case TIFF_RATIONAL: | |
172 | case TIFF_SRATIONAL: | |
173 | size = 4; | |
174 | break; | |
175 | ||
176 | case TIFF_DOUBLE: | |
177 | size = 8; | |
178 | break; | |
179 | } | |
180 | ||
181 | array = _TIFFmalloc(wc * size); | |
182 | if (!array) { | |
183 | fprintf(stderr, "No space for %s tag\n", | |
184 | tagname); | |
185 | return 4; | |
186 | } | |
187 | ||
80ed523f | 188 | switch (TIFFFieldDataType(fip)) { |
8414a40c VZ |
189 | case TIFF_BYTE: |
190 | for (i = 0; i < wc; i++) | |
191 | ((uint8 *)array)[i] = atoi(argv[arg_index+i]); | |
192 | break; | |
193 | case TIFF_SHORT: | |
194 | for (i = 0; i < wc; i++) | |
195 | ((uint16 *)array)[i] = atoi(argv[arg_index+i]); | |
196 | break; | |
197 | case TIFF_SBYTE: | |
198 | for (i = 0; i < wc; i++) | |
199 | ((int8 *)array)[i] = atoi(argv[arg_index+i]); | |
200 | break; | |
201 | case TIFF_SSHORT: | |
202 | for (i = 0; i < wc; i++) | |
203 | ((int16 *)array)[i] = atoi(argv[arg_index+i]); | |
204 | break; | |
205 | case TIFF_LONG: | |
206 | for (i = 0; i < wc; i++) | |
207 | ((uint32 *)array)[i] = atol(argv[arg_index+i]); | |
208 | break; | |
209 | case TIFF_SLONG: | |
210 | case TIFF_IFD: | |
211 | for (i = 0; i < wc; i++) | |
212 | ((uint32 *)array)[i] = atol(argv[arg_index+i]); | |
213 | break; | |
214 | case TIFF_DOUBLE: | |
215 | for (i = 0; i < wc; i++) | |
216 | ((double *)array)[i] = atof(argv[arg_index+i]); | |
217 | break; | |
218 | case TIFF_RATIONAL: | |
219 | case TIFF_SRATIONAL: | |
220 | case TIFF_FLOAT: | |
221 | for (i = 0; i < wc; i++) | |
222 | ((float *)array)[i] = (float)atof(argv[arg_index+i]); | |
223 | break; | |
224 | default: | |
225 | break; | |
226 | } | |
227 | ||
80ed523f VZ |
228 | if (TIFFFieldPassCount(fip)) { |
229 | ret = TIFFSetField(tiff, TIFFFieldTag(fip), | |
8414a40c | 230 | wc, array); |
80ed523f VZ |
231 | } else if (TIFFFieldTag(fip) == TIFFTAG_PAGENUMBER |
232 | || TIFFFieldTag(fip) == TIFFTAG_HALFTONEHINTS | |
233 | || TIFFFieldTag(fip) == TIFFTAG_YCBCRSUBSAMPLING | |
234 | || TIFFFieldTag(fip) == TIFFTAG_DOTRANGE) { | |
235 | if (TIFFFieldDataType(fip) == TIFF_BYTE) { | |
236 | ret = TIFFSetField(tiff, TIFFFieldTag(fip), | |
237 | ((uint8 *)array)[0], ((uint8 *)array)[1]); | |
238 | } else if (TIFFFieldDataType(fip) == TIFF_SHORT) { | |
239 | ret = TIFFSetField(tiff, TIFFFieldTag(fip), | |
240 | ((uint16 *)array)[0], ((uint16 *)array)[1]); | |
241 | } | |
242 | } else { | |
243 | ret = TIFFSetField(tiff, TIFFFieldTag(fip), | |
8414a40c VZ |
244 | array); |
245 | } | |
246 | ||
247 | _TIFFfree(array); | |
248 | } else { | |
80ed523f | 249 | switch (TIFFFieldDataType(fip)) { |
8414a40c VZ |
250 | case TIFF_BYTE: |
251 | case TIFF_SHORT: | |
252 | case TIFF_SBYTE: | |
253 | case TIFF_SSHORT: | |
80ed523f | 254 | ret = TIFFSetField(tiff, TIFFFieldTag(fip), |
8414a40c VZ |
255 | atoi(argv[arg_index++])); |
256 | break; | |
257 | case TIFF_LONG: | |
258 | case TIFF_SLONG: | |
259 | case TIFF_IFD: | |
80ed523f | 260 | ret = TIFFSetField(tiff, TIFFFieldTag(fip), |
8414a40c VZ |
261 | atol(argv[arg_index++])); |
262 | break; | |
263 | case TIFF_DOUBLE: | |
80ed523f | 264 | ret = TIFFSetField(tiff, TIFFFieldTag(fip), |
8414a40c VZ |
265 | atof(argv[arg_index++])); |
266 | break; | |
267 | case TIFF_RATIONAL: | |
268 | case TIFF_SRATIONAL: | |
269 | case TIFF_FLOAT: | |
80ed523f | 270 | ret = TIFFSetField(tiff, TIFFFieldTag(fip), |
8414a40c VZ |
271 | (float)atof(argv[arg_index++])); |
272 | break; | |
273 | default: | |
274 | break; | |
275 | } | |
276 | } | |
277 | ||
278 | if (ret != 1) | |
80ed523f | 279 | fprintf(stderr, "Failed to set %s\n", TIFFFieldName(fip)); |
8414a40c VZ |
280 | arg_index += wc; |
281 | } | |
282 | } else if (strcmp(argv[arg_index],"-sf") == 0 && arg_index < argc-3) { | |
283 | FILE *fp; | |
80ed523f | 284 | const TIFFField *fip; |
8414a40c | 285 | char *text; |
80ed523f | 286 | size_t len; |
8414a40c VZ |
287 | |
288 | arg_index++; | |
289 | fip = GetField(tiff, argv[arg_index]); | |
290 | ||
291 | if (!fip) | |
292 | return 3; | |
293 | ||
80ed523f | 294 | if (TIFFFieldDataType(fip) != TIFF_ASCII) { |
8414a40c VZ |
295 | fprintf( stderr, |
296 | "Only ASCII tags can be set from file. " | |
80ed523f | 297 | "%s is not ASCII tag.\n", TIFFFieldName(fip) ); |
8414a40c VZ |
298 | return 5; |
299 | } | |
300 | ||
301 | arg_index++; | |
302 | fp = fopen( argv[arg_index], "rt" ); | |
303 | if(fp == NULL) { | |
304 | perror( argv[arg_index] ); | |
305 | continue; | |
306 | } | |
307 | ||
308 | text = (char *) malloc(1000000); | |
309 | len = fread( text, 1, 999999, fp ); | |
310 | text[len] = '\0'; | |
311 | ||
312 | fclose( fp ); | |
313 | ||
80ed523f | 314 | if(TIFFSetField( tiff, TIFFFieldTag(fip), text ) != 1) { |
8414a40c | 315 | fprintf(stderr, "Failed to set %s from file %s\n", |
80ed523f | 316 | TIFFFieldName(fip), argv[arg_index]); |
8414a40c VZ |
317 | } |
318 | ||
319 | _TIFFfree( text ); | |
320 | arg_index++; | |
321 | } else { | |
322 | fprintf(stderr, "Unrecognised option: %s\n", | |
323 | argv[arg_index]); | |
324 | usage(); | |
325 | } | |
326 | } | |
327 | ||
328 | TIFFRewriteDirectory(tiff); | |
329 | TIFFClose(tiff); | |
330 | return 0; | |
331 | } | |
332 | ||
333 | /* vim: set ts=8 sts=8 sw=8 noet: */ | |
80ed523f VZ |
334 | /* |
335 | * Local Variables: | |
336 | * mode: c | |
337 | * c-basic-offset: 8 | |
338 | * fill-column: 78 | |
339 | * End: | |
340 | */ |