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