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