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