]>
Commit | Line | Data |
---|---|---|
8414a40c VZ |
1 | /* $Id$ */ |
2 | ||
3 | /* | |
4 | * Copyright (c) 1992-1997 Sam Leffler | |
5 | * Copyright (c) 1992-1997 Silicon Graphics, Inc. | |
6 | * | |
7 | * Permission to use, copy, modify, distribute, and sell this software and | |
8 | * its documentation for any purpose is hereby granted without fee, provided | |
9 | * that (i) the above copyright notices and this permission notice appear in | |
10 | * all copies of the software and related documentation, and (ii) the names of | |
11 | * Sam Leffler and Silicon Graphics may not be used in any advertising or | |
12 | * publicity relating to the software without the specific, prior written | |
13 | * permission of Sam Leffler and Silicon Graphics. | |
14 | * | |
15 | * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, | |
16 | * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY | |
17 | * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. | |
18 | * | |
19 | * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR | |
20 | * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, | |
21 | * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, | |
22 | * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF | |
23 | * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | |
24 | * OF THIS SOFTWARE. | |
25 | */ | |
26 | ||
27 | #include "tif_config.h" | |
28 | ||
29 | #include <stdio.h> | |
30 | #include <stdlib.h> | |
31 | #include <string.h> | |
32 | ||
33 | #include "tiffio.h" | |
34 | ||
35 | #ifndef HAVE_GETOPT | |
36 | extern int getopt(int, char**, char*); | |
37 | #endif | |
38 | ||
39 | #define CopyField(tag, v) \ | |
40 | if (TIFFGetField(in, tag, &v)) TIFFSetField(out, tag, v) | |
41 | #define CopyField2(tag, v1, v2) \ | |
42 | if (TIFFGetField(in, tag, &v1, &v2)) TIFFSetField(out, tag, v1, v2) | |
43 | #define CopyField3(tag, v1, v2, v3) \ | |
44 | if (TIFFGetField(in, tag, &v1, &v2, &v3)) TIFFSetField(out, tag, v1, v2, v3) | |
45 | ||
80ed523f VZ |
46 | #define PATH_LENGTH 8192 |
47 | ||
48 | static const char TIFF_SUFFIX[] = ".tif"; | |
49 | ||
50 | static char fname[PATH_LENGTH]; | |
8414a40c VZ |
51 | |
52 | static int tiffcp(TIFF*, TIFF*); | |
53 | static void newfilename(void); | |
54 | static int cpStrips(TIFF*, TIFF*); | |
55 | static int cpTiles(TIFF*, TIFF*); | |
56 | ||
57 | int | |
58 | main(int argc, char* argv[]) | |
59 | { | |
60 | TIFF *in, *out; | |
61 | ||
62 | if (argc < 2) { | |
63 | fprintf(stderr, "%s\n\n", TIFFGetVersion()); | |
64 | fprintf(stderr, "usage: tiffsplit input.tif [prefix]\n"); | |
65 | return (-3); | |
66 | } | |
80ed523f VZ |
67 | if (argc > 2) { |
68 | strncpy(fname, argv[2], sizeof(fname)); | |
69 | fname[sizeof(fname) - 1] = '\0'; | |
70 | } | |
8414a40c VZ |
71 | in = TIFFOpen(argv[1], "r"); |
72 | if (in != NULL) { | |
73 | do { | |
80ed523f VZ |
74 | size_t path_len; |
75 | char *path; | |
76 | ||
8414a40c | 77 | newfilename(); |
80ed523f VZ |
78 | |
79 | path_len = strlen(fname) + sizeof(TIFF_SUFFIX); | |
80 | path = (char *) _TIFFmalloc(path_len); | |
81 | strncpy(path, fname, path_len); | |
82 | path[path_len - 1] = '\0'; | |
83 | strncat(path, TIFF_SUFFIX, path_len - strlen(path) - 1); | |
8414a40c | 84 | out = TIFFOpen(path, TIFFIsBigEndian(in)?"wb":"wl"); |
80ed523f VZ |
85 | _TIFFfree(path); |
86 | ||
8414a40c VZ |
87 | if (out == NULL) |
88 | return (-2); | |
89 | if (!tiffcp(in, out)) | |
90 | return (-1); | |
91 | TIFFClose(out); | |
92 | } while (TIFFReadDirectory(in)); | |
93 | (void) TIFFClose(in); | |
94 | } | |
95 | return (0); | |
96 | } | |
97 | ||
98 | static void | |
99 | newfilename(void) | |
100 | { | |
101 | static int first = 1; | |
102 | static long lastTurn; | |
103 | static long fnum; | |
104 | static short defname; | |
105 | static char *fpnt; | |
106 | ||
107 | if (first) { | |
108 | if (fname[0]) { | |
109 | fpnt = fname + strlen(fname); | |
110 | defname = 0; | |
111 | } else { | |
112 | fname[0] = 'x'; | |
113 | fpnt = fname + 1; | |
114 | defname = 1; | |
115 | } | |
116 | first = 0; | |
117 | } | |
118 | #define MAXFILES 17576 | |
119 | if (fnum == MAXFILES) { | |
120 | if (!defname || fname[0] == 'z') { | |
121 | fprintf(stderr, "tiffsplit: too many files.\n"); | |
122 | exit(1); | |
123 | } | |
124 | fname[0]++; | |
125 | fnum = 0; | |
126 | } | |
127 | if (fnum % 676 == 0) { | |
128 | if (fnum != 0) { | |
129 | /* | |
130 | * advance to next letter every 676 pages | |
131 | * condition for 'z'++ will be covered above | |
132 | */ | |
133 | fpnt[0]++; | |
134 | } else { | |
135 | /* | |
136 | * set to 'a' if we are on the very first file | |
137 | */ | |
138 | fpnt[0] = 'a'; | |
139 | } | |
140 | /* | |
141 | * set the value of the last turning point | |
142 | */ | |
143 | lastTurn = fnum; | |
144 | } | |
145 | /* | |
146 | * start from 0 every 676 times (provided by lastTurn) | |
147 | * this keeps us within a-z boundaries | |
148 | */ | |
149 | fpnt[1] = (char)((fnum - lastTurn) / 26) + 'a'; | |
150 | /* | |
151 | * cycle last letter every file, from a-z, then repeat | |
152 | */ | |
153 | fpnt[2] = (char)(fnum % 26) + 'a'; | |
154 | fnum++; | |
155 | } | |
156 | ||
157 | static int | |
158 | tiffcp(TIFF* in, TIFF* out) | |
159 | { | |
160 | uint16 bitspersample, samplesperpixel, compression, shortv, *shortav; | |
161 | uint32 w, l; | |
162 | float floatv; | |
163 | char *stringv; | |
164 | uint32 longv; | |
165 | ||
166 | CopyField(TIFFTAG_SUBFILETYPE, longv); | |
167 | CopyField(TIFFTAG_TILEWIDTH, w); | |
168 | CopyField(TIFFTAG_TILELENGTH, l); | |
169 | CopyField(TIFFTAG_IMAGEWIDTH, w); | |
170 | CopyField(TIFFTAG_IMAGELENGTH, l); | |
171 | CopyField(TIFFTAG_BITSPERSAMPLE, bitspersample); | |
172 | CopyField(TIFFTAG_SAMPLESPERPIXEL, samplesperpixel); | |
173 | CopyField(TIFFTAG_COMPRESSION, compression); | |
174 | if (compression == COMPRESSION_JPEG) { | |
80ed523f | 175 | uint32 count = 0; |
8414a40c VZ |
176 | void *table = NULL; |
177 | if (TIFFGetField(in, TIFFTAG_JPEGTABLES, &count, &table) | |
178 | && count > 0 && table) { | |
179 | TIFFSetField(out, TIFFTAG_JPEGTABLES, count, table); | |
180 | } | |
181 | } | |
182 | CopyField(TIFFTAG_PHOTOMETRIC, shortv); | |
183 | CopyField(TIFFTAG_PREDICTOR, shortv); | |
184 | CopyField(TIFFTAG_THRESHHOLDING, shortv); | |
185 | CopyField(TIFFTAG_FILLORDER, shortv); | |
186 | CopyField(TIFFTAG_ORIENTATION, shortv); | |
187 | CopyField(TIFFTAG_MINSAMPLEVALUE, shortv); | |
188 | CopyField(TIFFTAG_MAXSAMPLEVALUE, shortv); | |
189 | CopyField(TIFFTAG_XRESOLUTION, floatv); | |
190 | CopyField(TIFFTAG_YRESOLUTION, floatv); | |
191 | CopyField(TIFFTAG_GROUP3OPTIONS, longv); | |
192 | CopyField(TIFFTAG_GROUP4OPTIONS, longv); | |
193 | CopyField(TIFFTAG_RESOLUTIONUNIT, shortv); | |
194 | CopyField(TIFFTAG_PLANARCONFIG, shortv); | |
195 | CopyField(TIFFTAG_ROWSPERSTRIP, longv); | |
196 | CopyField(TIFFTAG_XPOSITION, floatv); | |
197 | CopyField(TIFFTAG_YPOSITION, floatv); | |
198 | CopyField(TIFFTAG_IMAGEDEPTH, longv); | |
199 | CopyField(TIFFTAG_TILEDEPTH, longv); | |
80ed523f | 200 | CopyField(TIFFTAG_SAMPLEFORMAT, shortv); |
8414a40c VZ |
201 | CopyField2(TIFFTAG_EXTRASAMPLES, shortv, shortav); |
202 | { uint16 *red, *green, *blue; | |
203 | CopyField3(TIFFTAG_COLORMAP, red, green, blue); | |
204 | } | |
205 | { uint16 shortv2; | |
206 | CopyField2(TIFFTAG_PAGENUMBER, shortv, shortv2); | |
207 | } | |
208 | CopyField(TIFFTAG_ARTIST, stringv); | |
209 | CopyField(TIFFTAG_IMAGEDESCRIPTION, stringv); | |
210 | CopyField(TIFFTAG_MAKE, stringv); | |
211 | CopyField(TIFFTAG_MODEL, stringv); | |
212 | CopyField(TIFFTAG_SOFTWARE, stringv); | |
213 | CopyField(TIFFTAG_DATETIME, stringv); | |
214 | CopyField(TIFFTAG_HOSTCOMPUTER, stringv); | |
215 | CopyField(TIFFTAG_PAGENAME, stringv); | |
216 | CopyField(TIFFTAG_DOCUMENTNAME, stringv); | |
217 | CopyField(TIFFTAG_BADFAXLINES, longv); | |
218 | CopyField(TIFFTAG_CLEANFAXDATA, longv); | |
219 | CopyField(TIFFTAG_CONSECUTIVEBADFAXLINES, longv); | |
220 | CopyField(TIFFTAG_FAXRECVPARAMS, longv); | |
221 | CopyField(TIFFTAG_FAXRECVTIME, longv); | |
222 | CopyField(TIFFTAG_FAXSUBADDRESS, stringv); | |
223 | CopyField(TIFFTAG_FAXDCS, stringv); | |
224 | if (TIFFIsTiled(in)) | |
225 | return (cpTiles(in, out)); | |
226 | else | |
227 | return (cpStrips(in, out)); | |
228 | } | |
229 | ||
230 | static int | |
231 | cpStrips(TIFF* in, TIFF* out) | |
232 | { | |
80ed523f | 233 | tmsize_t bufsize = TIFFStripSize(in); |
8414a40c VZ |
234 | unsigned char *buf = (unsigned char *)_TIFFmalloc(bufsize); |
235 | ||
236 | if (buf) { | |
237 | tstrip_t s, ns = TIFFNumberOfStrips(in); | |
80ed523f | 238 | uint64 *bytecounts; |
8414a40c | 239 | |
80ed523f VZ |
240 | if (!TIFFGetField(in, TIFFTAG_STRIPBYTECOUNTS, &bytecounts)) { |
241 | fprintf(stderr, "tiffsplit: strip byte counts are missing\n"); | |
242 | return (0); | |
243 | } | |
8414a40c | 244 | for (s = 0; s < ns; s++) { |
80ed523f VZ |
245 | if (bytecounts[s] > (uint64)bufsize) { |
246 | buf = (unsigned char *)_TIFFrealloc(buf, (tmsize_t)bytecounts[s]); | |
8414a40c VZ |
247 | if (!buf) |
248 | return (0); | |
80ed523f | 249 | bufsize = (tmsize_t)bytecounts[s]; |
8414a40c | 250 | } |
80ed523f VZ |
251 | if (TIFFReadRawStrip(in, s, buf, (tmsize_t)bytecounts[s]) < 0 || |
252 | TIFFWriteRawStrip(out, s, buf, (tmsize_t)bytecounts[s]) < 0) { | |
8414a40c VZ |
253 | _TIFFfree(buf); |
254 | return (0); | |
255 | } | |
256 | } | |
257 | _TIFFfree(buf); | |
258 | return (1); | |
259 | } | |
260 | return (0); | |
261 | } | |
262 | ||
263 | static int | |
264 | cpTiles(TIFF* in, TIFF* out) | |
265 | { | |
80ed523f | 266 | tmsize_t bufsize = TIFFTileSize(in); |
8414a40c VZ |
267 | unsigned char *buf = (unsigned char *)_TIFFmalloc(bufsize); |
268 | ||
269 | if (buf) { | |
270 | ttile_t t, nt = TIFFNumberOfTiles(in); | |
80ed523f | 271 | uint64 *bytecounts; |
8414a40c | 272 | |
80ed523f VZ |
273 | if (!TIFFGetField(in, TIFFTAG_TILEBYTECOUNTS, &bytecounts)) { |
274 | fprintf(stderr, "tiffsplit: tile byte counts are missing\n"); | |
275 | return (0); | |
276 | } | |
8414a40c | 277 | for (t = 0; t < nt; t++) { |
80ed523f VZ |
278 | if (bytecounts[t] > (uint64) bufsize) { |
279 | buf = (unsigned char *)_TIFFrealloc(buf, (tmsize_t)bytecounts[t]); | |
8414a40c VZ |
280 | if (!buf) |
281 | return (0); | |
80ed523f | 282 | bufsize = (tmsize_t)bytecounts[t]; |
8414a40c | 283 | } |
80ed523f VZ |
284 | if (TIFFReadRawTile(in, t, buf, (tmsize_t)bytecounts[t]) < 0 || |
285 | TIFFWriteRawTile(out, t, buf, (tmsize_t)bytecounts[t]) < 0) { | |
8414a40c VZ |
286 | _TIFFfree(buf); |
287 | return (0); | |
288 | } | |
289 | } | |
290 | _TIFFfree(buf); | |
291 | return (1); | |
292 | } | |
293 | return (0); | |
294 | } | |
295 | ||
296 | /* vim: set ts=8 sts=8 sw=8 noet: */ | |
80ed523f VZ |
297 | /* |
298 | * Local Variables: | |
299 | * mode: c | |
300 | * c-basic-offset: 8 | |
301 | * fill-column: 78 | |
302 | * End: | |
303 | */ |