1 /* $Id: tiffsplit.c,v 1.23 2015-05-28 13:10:26 bfriesen 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 const char TIFF_SUFFIX[] = ".tif";
49 
50 static	char fname[PATH_LENGTH];
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
main(int argc,char * argv[])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 	}
67 	if (argc > 2) {
68 		strncpy(fname, argv[2], sizeof(fname));
69 		fname[sizeof(fname) - 1] = '\0';
70 	}
71 	in = TIFFOpen(argv[1], "r");
72 	if (in != NULL) {
73 		do {
74 			size_t path_len;
75 			char *path;
76 
77 			newfilename();
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);
84 			out = TIFFOpen(path, TIFFIsBigEndian(in)?"wb":"wl");
85 			_TIFFfree(path);
86 
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
newfilename(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
tiffcp(TIFF * in,TIFF * out)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) {
175 		uint32 count = 0;
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);
200 	CopyField(TIFFTAG_SAMPLEFORMAT, shortv);
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
cpStrips(TIFF * in,TIFF * out)231 cpStrips(TIFF* in, TIFF* out)
232 {
233 	tmsize_t bufsize  = TIFFStripSize(in);
234 	unsigned char *buf = (unsigned char *)_TIFFmalloc(bufsize);
235 
236 	if (buf) {
237 		tstrip_t s, ns = TIFFNumberOfStrips(in);
238 		uint64 *bytecounts;
239 
240 		if (!TIFFGetField(in, TIFFTAG_STRIPBYTECOUNTS, &bytecounts)) {
241 			fprintf(stderr, "tiffsplit: strip byte counts are missing\n");
242                         _TIFFfree(buf);
243 			return (0);
244 		}
245 		for (s = 0; s < ns; s++) {
246 			if (bytecounts[s] > (uint64)bufsize) {
247 				buf = (unsigned char *)_TIFFrealloc(buf, (tmsize_t)bytecounts[s]);
248 				if (!buf)
249 					return (0);
250 				bufsize = (tmsize_t)bytecounts[s];
251 			}
252 			if (TIFFReadRawStrip(in, s, buf, (tmsize_t)bytecounts[s]) < 0 ||
253 			    TIFFWriteRawStrip(out, s, buf, (tmsize_t)bytecounts[s]) < 0) {
254 				_TIFFfree(buf);
255 				return (0);
256 			}
257 		}
258 		_TIFFfree(buf);
259 		return (1);
260 	}
261 	return (0);
262 }
263 
264 static int
cpTiles(TIFF * in,TIFF * out)265 cpTiles(TIFF* in, TIFF* out)
266 {
267 	tmsize_t bufsize = TIFFTileSize(in);
268 	unsigned char *buf = (unsigned char *)_TIFFmalloc(bufsize);
269 
270 	if (buf) {
271 		ttile_t t, nt = TIFFNumberOfTiles(in);
272 		uint64 *bytecounts;
273 
274 		if (!TIFFGetField(in, TIFFTAG_TILEBYTECOUNTS, &bytecounts)) {
275 			fprintf(stderr, "tiffsplit: tile byte counts are missing\n");
276                         _TIFFfree(buf);
277 			return (0);
278 		}
279 		for (t = 0; t < nt; t++) {
280 			if (bytecounts[t] > (uint64) bufsize) {
281 				buf = (unsigned char *)_TIFFrealloc(buf, (tmsize_t)bytecounts[t]);
282 				if (!buf)
283 					return (0);
284 				bufsize = (tmsize_t)bytecounts[t];
285 			}
286 			if (TIFFReadRawTile(in, t, buf, (tmsize_t)bytecounts[t]) < 0 ||
287 			    TIFFWriteRawTile(out, t, buf, (tmsize_t)bytecounts[t]) < 0) {
288 				_TIFFfree(buf);
289 				return (0);
290 			}
291 		}
292 		_TIFFfree(buf);
293 		return (1);
294 	}
295 	return (0);
296 }
297 
298 /* vim: set ts=8 sts=8 sw=8 noet: */
299 /*
300  * Local Variables:
301  * mode: c
302  * c-basic-offset: 8
303  * fill-column: 78
304  * End:
305  */
306