1/* $Id: tiffsplit.c 276 2010-06-30 12:18:30Z nijtmans $ */ 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 36extern 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 48static const char TIFF_SUFFIX[] = ".tif"; 49 50static char fname[PATH_LENGTH]; 51 52static int tiffcp(TIFF*, TIFF*); 53static void newfilename(void); 54static int cpStrips(TIFF*, TIFF*); 55static int cpTiles(TIFF*, TIFF*); 56 57int 58main(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 98static void 99newfilename(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 157static int 158tiffcp(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 uint16 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 230static int 231cpStrips(TIFF* in, TIFF* out) 232{ 233 tsize_t bufsize = TIFFStripSize(in); 234 unsigned char *buf = (unsigned char *)_TIFFmalloc(bufsize); 235 236 if (buf) { 237 tstrip_t s, ns = TIFFNumberOfStrips(in); 238 uint32 *bytecounts; 239 240 TIFFGetField(in, TIFFTAG_STRIPBYTECOUNTS, &bytecounts); 241 for (s = 0; s < ns; s++) { 242 if (bytecounts[s] > (uint32)bufsize) { 243 buf = (unsigned char *)_TIFFrealloc(buf, bytecounts[s]); 244 if (!buf) 245 return (0); 246 bufsize = bytecounts[s]; 247 } 248 if (TIFFReadRawStrip(in, s, buf, bytecounts[s]) < 0 || 249 TIFFWriteRawStrip(out, s, buf, bytecounts[s]) < 0) { 250 _TIFFfree(buf); 251 return (0); 252 } 253 } 254 _TIFFfree(buf); 255 return (1); 256 } 257 return (0); 258} 259 260static int 261cpTiles(TIFF* in, TIFF* out) 262{ 263 tsize_t bufsize = TIFFTileSize(in); 264 unsigned char *buf = (unsigned char *)_TIFFmalloc(bufsize); 265 266 if (buf) { 267 ttile_t t, nt = TIFFNumberOfTiles(in); 268 uint32 *bytecounts; 269 270 TIFFGetField(in, TIFFTAG_TILEBYTECOUNTS, &bytecounts); 271 for (t = 0; t < nt; t++) { 272 if (bytecounts[t] > (uint32) bufsize) { 273 buf = (unsigned char *)_TIFFrealloc(buf, bytecounts[t]); 274 if (!buf) 275 return (0); 276 bufsize = bytecounts[t]; 277 } 278 if (TIFFReadRawTile(in, t, buf, bytecounts[t]) < 0 || 279 TIFFWriteRawTile(out, t, buf, bytecounts[t]) < 0) { 280 _TIFFfree(buf); 281 return (0); 282 } 283 } 284 _TIFFfree(buf); 285 return (1); 286 } 287 return (0); 288} 289 290/* vim: set ts=8 sts=8 sw=8 noet: */ 291/* 292 * Local Variables: 293 * mode: c 294 * c-basic-offset: 8 295 * fill-column: 78 296 * End: 297 */ 298