]>
Commit | Line | Data |
---|---|---|
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 | ||
46 | static char fname[1024+1]; | |
47 | ||
48 | static int tiffcp(TIFF*, TIFF*); | |
49 | static void newfilename(void); | |
50 | static int cpStrips(TIFF*, TIFF*); | |
51 | static int cpTiles(TIFF*, TIFF*); | |
52 | ||
53 | int | |
54 | main(int argc, char* argv[]) | |
55 | { | |
56 | TIFF *in, *out; | |
57 | ||
58 | if (argc < 2) { | |
59 | fprintf(stderr, "%s\n\n", TIFFGetVersion()); | |
60 | fprintf(stderr, "usage: tiffsplit input.tif [prefix]\n"); | |
61 | return (-3); | |
62 | } | |
63 | if (argc > 2) | |
64 | strcpy(fname, argv[2]); | |
65 | in = TIFFOpen(argv[1], "r"); | |
66 | if (in != NULL) { | |
67 | do { | |
68 | char path[1024+1]; | |
69 | newfilename(); | |
70 | strcpy(path, fname); | |
71 | strcat(path, ".tif"); | |
72 | out = TIFFOpen(path, TIFFIsBigEndian(in)?"wb":"wl"); | |
73 | if (out == NULL) | |
74 | return (-2); | |
75 | if (!tiffcp(in, out)) | |
76 | return (-1); | |
77 | TIFFClose(out); | |
78 | } while (TIFFReadDirectory(in)); | |
79 | (void) TIFFClose(in); | |
80 | } | |
81 | return (0); | |
82 | } | |
83 | ||
84 | static void | |
85 | newfilename(void) | |
86 | { | |
87 | static int first = 1; | |
88 | static long lastTurn; | |
89 | static long fnum; | |
90 | static short defname; | |
91 | static char *fpnt; | |
92 | ||
93 | if (first) { | |
94 | if (fname[0]) { | |
95 | fpnt = fname + strlen(fname); | |
96 | defname = 0; | |
97 | } else { | |
98 | fname[0] = 'x'; | |
99 | fpnt = fname + 1; | |
100 | defname = 1; | |
101 | } | |
102 | first = 0; | |
103 | } | |
104 | #define MAXFILES 17576 | |
105 | if (fnum == MAXFILES) { | |
106 | if (!defname || fname[0] == 'z') { | |
107 | fprintf(stderr, "tiffsplit: too many files.\n"); | |
108 | exit(1); | |
109 | } | |
110 | fname[0]++; | |
111 | fnum = 0; | |
112 | } | |
113 | if (fnum % 676 == 0) { | |
114 | if (fnum != 0) { | |
115 | /* | |
116 | * advance to next letter every 676 pages | |
117 | * condition for 'z'++ will be covered above | |
118 | */ | |
119 | fpnt[0]++; | |
120 | } else { | |
121 | /* | |
122 | * set to 'a' if we are on the very first file | |
123 | */ | |
124 | fpnt[0] = 'a'; | |
125 | } | |
126 | /* | |
127 | * set the value of the last turning point | |
128 | */ | |
129 | lastTurn = fnum; | |
130 | } | |
131 | /* | |
132 | * start from 0 every 676 times (provided by lastTurn) | |
133 | * this keeps us within a-z boundaries | |
134 | */ | |
135 | fpnt[1] = (char)((fnum - lastTurn) / 26) + 'a'; | |
136 | /* | |
137 | * cycle last letter every file, from a-z, then repeat | |
138 | */ | |
139 | fpnt[2] = (char)(fnum % 26) + 'a'; | |
140 | fnum++; | |
141 | } | |
142 | ||
143 | static int | |
144 | tiffcp(TIFF* in, TIFF* out) | |
145 | { | |
146 | uint16 bitspersample, samplesperpixel, compression, shortv, *shortav; | |
147 | uint32 w, l; | |
148 | float floatv; | |
149 | char *stringv; | |
150 | uint32 longv; | |
151 | ||
152 | CopyField(TIFFTAG_SUBFILETYPE, longv); | |
153 | CopyField(TIFFTAG_TILEWIDTH, w); | |
154 | CopyField(TIFFTAG_TILELENGTH, l); | |
155 | CopyField(TIFFTAG_IMAGEWIDTH, w); | |
156 | CopyField(TIFFTAG_IMAGELENGTH, l); | |
157 | CopyField(TIFFTAG_BITSPERSAMPLE, bitspersample); | |
158 | CopyField(TIFFTAG_SAMPLESPERPIXEL, samplesperpixel); | |
159 | CopyField(TIFFTAG_COMPRESSION, compression); | |
160 | if (compression == COMPRESSION_JPEG) { | |
161 | uint16 count = 0; | |
162 | void *table = NULL; | |
163 | if (TIFFGetField(in, TIFFTAG_JPEGTABLES, &count, &table) | |
164 | && count > 0 && table) { | |
165 | TIFFSetField(out, TIFFTAG_JPEGTABLES, count, table); | |
166 | } | |
167 | } | |
168 | CopyField(TIFFTAG_PHOTOMETRIC, shortv); | |
169 | CopyField(TIFFTAG_PREDICTOR, shortv); | |
170 | CopyField(TIFFTAG_THRESHHOLDING, shortv); | |
171 | CopyField(TIFFTAG_FILLORDER, shortv); | |
172 | CopyField(TIFFTAG_ORIENTATION, shortv); | |
173 | CopyField(TIFFTAG_MINSAMPLEVALUE, shortv); | |
174 | CopyField(TIFFTAG_MAXSAMPLEVALUE, shortv); | |
175 | CopyField(TIFFTAG_XRESOLUTION, floatv); | |
176 | CopyField(TIFFTAG_YRESOLUTION, floatv); | |
177 | CopyField(TIFFTAG_GROUP3OPTIONS, longv); | |
178 | CopyField(TIFFTAG_GROUP4OPTIONS, longv); | |
179 | CopyField(TIFFTAG_RESOLUTIONUNIT, shortv); | |
180 | CopyField(TIFFTAG_PLANARCONFIG, shortv); | |
181 | CopyField(TIFFTAG_ROWSPERSTRIP, longv); | |
182 | CopyField(TIFFTAG_XPOSITION, floatv); | |
183 | CopyField(TIFFTAG_YPOSITION, floatv); | |
184 | CopyField(TIFFTAG_IMAGEDEPTH, longv); | |
185 | CopyField(TIFFTAG_TILEDEPTH, longv); | |
186 | CopyField(TIFFTAG_SAMPLEFORMAT, longv); | |
187 | CopyField2(TIFFTAG_EXTRASAMPLES, shortv, shortav); | |
188 | { uint16 *red, *green, *blue; | |
189 | CopyField3(TIFFTAG_COLORMAP, red, green, blue); | |
190 | } | |
191 | { uint16 shortv2; | |
192 | CopyField2(TIFFTAG_PAGENUMBER, shortv, shortv2); | |
193 | } | |
194 | CopyField(TIFFTAG_ARTIST, stringv); | |
195 | CopyField(TIFFTAG_IMAGEDESCRIPTION, stringv); | |
196 | CopyField(TIFFTAG_MAKE, stringv); | |
197 | CopyField(TIFFTAG_MODEL, stringv); | |
198 | CopyField(TIFFTAG_SOFTWARE, stringv); | |
199 | CopyField(TIFFTAG_DATETIME, stringv); | |
200 | CopyField(TIFFTAG_HOSTCOMPUTER, stringv); | |
201 | CopyField(TIFFTAG_PAGENAME, stringv); | |
202 | CopyField(TIFFTAG_DOCUMENTNAME, stringv); | |
203 | CopyField(TIFFTAG_BADFAXLINES, longv); | |
204 | CopyField(TIFFTAG_CLEANFAXDATA, longv); | |
205 | CopyField(TIFFTAG_CONSECUTIVEBADFAXLINES, longv); | |
206 | CopyField(TIFFTAG_FAXRECVPARAMS, longv); | |
207 | CopyField(TIFFTAG_FAXRECVTIME, longv); | |
208 | CopyField(TIFFTAG_FAXSUBADDRESS, stringv); | |
209 | CopyField(TIFFTAG_FAXDCS, stringv); | |
210 | if (TIFFIsTiled(in)) | |
211 | return (cpTiles(in, out)); | |
212 | else | |
213 | return (cpStrips(in, out)); | |
214 | } | |
215 | ||
216 | static int | |
217 | cpStrips(TIFF* in, TIFF* out) | |
218 | { | |
219 | tsize_t bufsize = TIFFStripSize(in); | |
220 | unsigned char *buf = (unsigned char *)_TIFFmalloc(bufsize); | |
221 | ||
222 | if (buf) { | |
223 | tstrip_t s, ns = TIFFNumberOfStrips(in); | |
224 | uint32 *bytecounts; | |
225 | ||
226 | TIFFGetField(in, TIFFTAG_STRIPBYTECOUNTS, &bytecounts); | |
227 | for (s = 0; s < ns; s++) { | |
228 | if (bytecounts[s] > (uint32)bufsize) { | |
229 | buf = (unsigned char *)_TIFFrealloc(buf, bytecounts[s]); | |
230 | if (!buf) | |
231 | return (0); | |
232 | bufsize = bytecounts[s]; | |
233 | } | |
234 | if (TIFFReadRawStrip(in, s, buf, bytecounts[s]) < 0 || | |
235 | TIFFWriteRawStrip(out, s, buf, bytecounts[s]) < 0) { | |
236 | _TIFFfree(buf); | |
237 | return (0); | |
238 | } | |
239 | } | |
240 | _TIFFfree(buf); | |
241 | return (1); | |
242 | } | |
243 | return (0); | |
244 | } | |
245 | ||
246 | static int | |
247 | cpTiles(TIFF* in, TIFF* out) | |
248 | { | |
249 | tsize_t bufsize = TIFFTileSize(in); | |
250 | unsigned char *buf = (unsigned char *)_TIFFmalloc(bufsize); | |
251 | ||
252 | if (buf) { | |
253 | ttile_t t, nt = TIFFNumberOfTiles(in); | |
254 | uint32 *bytecounts; | |
255 | ||
256 | TIFFGetField(in, TIFFTAG_TILEBYTECOUNTS, &bytecounts); | |
257 | for (t = 0; t < nt; t++) { | |
258 | if (bytecounts[t] > (uint32) bufsize) { | |
259 | buf = (unsigned char *)_TIFFrealloc(buf, bytecounts[t]); | |
260 | if (!buf) | |
261 | return (0); | |
262 | bufsize = bytecounts[t]; | |
263 | } | |
264 | if (TIFFReadRawTile(in, t, buf, bytecounts[t]) < 0 || | |
265 | TIFFWriteRawTile(out, t, buf, bytecounts[t]) < 0) { | |
266 | _TIFFfree(buf); | |
267 | return (0); | |
268 | } | |
269 | } | |
270 | _TIFFfree(buf); | |
271 | return (1); | |
272 | } | |
273 | return (0); | |
274 | } | |
275 | ||
276 | /* vim: set ts=8 sts=8 sw=8 noet: */ |