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