1/* $Id: raw2tiff.c 276 2010-06-30 12:18:30Z nijtmans $ 2 * 3 * Project: libtiff tools 4 * Purpose: Convert raw byte sequences in TIFF images 5 * Author: Andrey Kiselev, dron@ak4719.spb.edu 6 * 7 ****************************************************************************** 8 * Copyright (c) 2002, Andrey Kiselev <dron@ak4719.spb.edu> 9 * 10 * Permission to use, copy, modify, distribute, and sell this software and 11 * its documentation for any purpose is hereby granted without fee, provided 12 * that (i) the above copyright notices and this permission notice appear in 13 * all copies of the software and related documentation, and (ii) the names of 14 * Sam Leffler and Silicon Graphics may not be used in any advertising or 15 * publicity relating to the software without the specific, prior written 16 * permission of Sam Leffler and Silicon Graphics. 17 * 18 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 19 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 20 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. 21 * 22 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR 23 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, 24 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 25 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 26 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 27 * OF THIS SOFTWARE. 28 */ 29 30#include "tif_config.h" 31 32#include <stdio.h> 33#include <stdlib.h> 34#include <string.h> 35#include <sys/stat.h> 36#include <sys/types.h> 37#include <math.h> 38#include <ctype.h> 39 40#ifdef HAVE_UNISTD_H 41# include <unistd.h> 42#endif 43 44#if HAVE_FCNTL_H 45# include <fcntl.h> 46#endif 47 48#if HAVE_SYS_TYPES_H 49# include <sys/types.h> 50#endif 51 52#if HAVE_IO_H 53# include <io.h> 54#endif 55 56#include "tiffio.h" 57 58#ifndef HAVE_GETOPT 59extern int getopt(int, char**, char*); 60#endif 61 62#ifndef O_BINARY 63# define O_BINARY 0 64#endif 65 66typedef enum { 67 PIXEL, 68 BAND 69} InterleavingType; 70 71static uint16 compression = (uint16) -1; 72static int jpegcolormode = JPEGCOLORMODE_RGB; 73static int quality = 75; /* JPEG quality */ 74static uint16 predictor = 0; 75 76static void swapBytesInScanline(void *, uint32, TIFFDataType); 77static int guessSize(int, TIFFDataType, off_t, uint32, int, 78 uint32 *, uint32 *); 79static double correlation(void *, void *, uint32, TIFFDataType); 80static void usage(void); 81static int processCompressOptions(char*); 82 83int 84main(int argc, char* argv[]) 85{ 86 uint32 width = 0, length = 0, linebytes, bufsize; 87 uint32 nbands = 1; /* number of bands in input image*/ 88 off_t hdr_size = 0; /* size of the header to skip */ 89 TIFFDataType dtype = TIFF_BYTE; 90 int16 depth = 1; /* bytes per pixel in input image */ 91 int swab = 0; /* byte swapping flag */ 92 InterleavingType interleaving = 0; /* interleaving type flag */ 93 uint32 rowsperstrip = (uint32) -1; 94 uint16 photometric = PHOTOMETRIC_MINISBLACK; 95 uint16 config = PLANARCONFIG_CONTIG; 96 uint16 fillorder = FILLORDER_LSB2MSB; 97 int fd; 98 char *outfilename = NULL; 99 TIFF *out; 100 101 uint32 row, col, band; 102 int c; 103 unsigned char *buf = NULL, *buf1 = NULL; 104 extern int optind; 105 extern char* optarg; 106 107 while ((c = getopt(argc, argv, "c:r:H:w:l:b:d:LMp:si:o:h")) != -1) { 108 switch (c) { 109 case 'c': /* compression scheme */ 110 if (!processCompressOptions(optarg)) 111 usage(); 112 break; 113 case 'r': /* rows/strip */ 114 rowsperstrip = atoi(optarg); 115 break; 116 case 'H': /* size of input image file header */ 117 hdr_size = atoi(optarg); 118 break; 119 case 'w': /* input image width */ 120 width = atoi(optarg); 121 break; 122 case 'l': /* input image length */ 123 length = atoi(optarg); 124 break; 125 case 'b': /* number of bands in input image */ 126 nbands = atoi(optarg); 127 break; 128 case 'd': /* type of samples in input image */ 129 if (strncmp(optarg, "byte", 4) == 0) 130 dtype = TIFF_BYTE; 131 else if (strncmp(optarg, "short", 5) == 0) 132 dtype = TIFF_SHORT; 133 else if (strncmp(optarg, "long", 4) == 0) 134 dtype = TIFF_LONG; 135 else if (strncmp(optarg, "sbyte", 5) == 0) 136 dtype = TIFF_SBYTE; 137 else if (strncmp(optarg, "sshort", 6) == 0) 138 dtype = TIFF_SSHORT; 139 else if (strncmp(optarg, "slong", 5) == 0) 140 dtype = TIFF_SLONG; 141 else if (strncmp(optarg, "float", 5) == 0) 142 dtype = TIFF_FLOAT; 143 else if (strncmp(optarg, "double", 6) == 0) 144 dtype = TIFF_DOUBLE; 145 else 146 dtype = TIFF_BYTE; 147 depth = TIFFDataWidth(dtype); 148 break; 149 case 'L': /* input has lsb-to-msb fillorder */ 150 fillorder = FILLORDER_LSB2MSB; 151 break; 152 case 'M': /* input has msb-to-lsb fillorder */ 153 fillorder = FILLORDER_MSB2LSB; 154 break; 155 case 'p': /* photometric interpretation */ 156 if (strncmp(optarg, "miniswhite", 10) == 0) 157 photometric = PHOTOMETRIC_MINISWHITE; 158 else if (strncmp(optarg, "minisblack", 10) == 0) 159 photometric = PHOTOMETRIC_MINISBLACK; 160 else if (strncmp(optarg, "rgb", 3) == 0) 161 photometric = PHOTOMETRIC_RGB; 162 else if (strncmp(optarg, "cmyk", 4) == 0) 163 photometric = PHOTOMETRIC_SEPARATED; 164 else if (strncmp(optarg, "ycbcr", 5) == 0) 165 photometric = PHOTOMETRIC_YCBCR; 166 else if (strncmp(optarg, "cielab", 6) == 0) 167 photometric = PHOTOMETRIC_CIELAB; 168 else if (strncmp(optarg, "icclab", 6) == 0) 169 photometric = PHOTOMETRIC_ICCLAB; 170 else if (strncmp(optarg, "itulab", 6) == 0) 171 photometric = PHOTOMETRIC_ITULAB; 172 else 173 photometric = PHOTOMETRIC_MINISBLACK; 174 break; 175 case 's': /* do we need to swap bytes? */ 176 swab = 1; 177 break; 178 case 'i': /* type of interleaving */ 179 if (strncmp(optarg, "pixel", 4) == 0) 180 interleaving = PIXEL; 181 else if (strncmp(optarg, "band", 6) == 0) 182 interleaving = BAND; 183 else 184 interleaving = 0; 185 break; 186 case 'o': 187 outfilename = optarg; 188 break; 189 case 'h': 190 usage(); 191 default: 192 break; 193 } 194 } 195 196 if (argc - optind < 2) 197 usage(); 198 199 fd = open(argv[optind], O_RDONLY|O_BINARY, 0); 200 if (fd < 0) { 201 fprintf(stderr, "%s: %s: Cannot open input file.\n", 202 argv[0], argv[optind]); 203 return (-1); 204 } 205 206 if (guessSize(fd, dtype, hdr_size, nbands, swab, &width, &length) < 0) 207 return 1; 208 209 if (outfilename == NULL) 210 outfilename = argv[optind+1]; 211 out = TIFFOpen(outfilename, "w"); 212 if (out == NULL) { 213 fprintf(stderr, "%s: %s: Cannot open file for output.\n", 214 argv[0], outfilename); 215 return (-1); 216 } 217 TIFFSetField(out, TIFFTAG_IMAGEWIDTH, width); 218 TIFFSetField(out, TIFFTAG_IMAGELENGTH, length); 219 TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); 220 TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, nbands); 221 TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, depth * 8); 222 TIFFSetField(out, TIFFTAG_FILLORDER, fillorder); 223 TIFFSetField(out, TIFFTAG_PLANARCONFIG, config); 224 TIFFSetField(out, TIFFTAG_PHOTOMETRIC, photometric); 225 switch (dtype) { 226 case TIFF_BYTE: 227 case TIFF_SHORT: 228 case TIFF_LONG: 229 TIFFSetField(out, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT); 230 break; 231 case TIFF_SBYTE: 232 case TIFF_SSHORT: 233 case TIFF_SLONG: 234 TIFFSetField(out, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_INT); 235 break; 236 case TIFF_FLOAT: 237 case TIFF_DOUBLE: 238 TIFFSetField(out, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP); 239 break; 240 default: 241 TIFFSetField(out, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_VOID); 242 break; 243 } 244 if (compression == (uint16) -1) 245 compression = COMPRESSION_PACKBITS; 246 TIFFSetField(out, TIFFTAG_COMPRESSION, compression); 247 switch (compression) { 248 case COMPRESSION_JPEG: 249 if (photometric == PHOTOMETRIC_RGB 250 && jpegcolormode == JPEGCOLORMODE_RGB) 251 photometric = PHOTOMETRIC_YCBCR; 252 TIFFSetField(out, TIFFTAG_JPEGQUALITY, quality); 253 TIFFSetField(out, TIFFTAG_JPEGCOLORMODE, jpegcolormode); 254 break; 255 case COMPRESSION_LZW: 256 case COMPRESSION_DEFLATE: 257 if (predictor != 0) 258 TIFFSetField(out, TIFFTAG_PREDICTOR, predictor); 259 break; 260 } 261 switch(interleaving) { 262 case BAND: /* band interleaved data */ 263 linebytes = width * depth; 264 buf = (unsigned char *)_TIFFmalloc(linebytes); 265 break; 266 case PIXEL: /* pixel interleaved data */ 267 default: 268 linebytes = width * nbands * depth; 269 break; 270 } 271 bufsize = width * nbands * depth; 272 buf1 = (unsigned char *)_TIFFmalloc(bufsize); 273 274 rowsperstrip = TIFFDefaultStripSize(out, rowsperstrip); 275 if (rowsperstrip > length) { 276 rowsperstrip = length; 277 } 278 TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, rowsperstrip ); 279 280 lseek(fd, hdr_size, SEEK_SET); /* Skip the file header */ 281 for (row = 0; row < length; row++) { 282 switch(interleaving) { 283 case BAND: /* band interleaved data */ 284 for (band = 0; band < nbands; band++) { 285 lseek(fd, 286 hdr_size + (length*band+row)*linebytes, 287 SEEK_SET); 288 if (read(fd, buf, linebytes) < 0) { 289 fprintf(stderr, 290 "%s: %s: scanline %lu: Read error.\n", 291 argv[0], argv[optind], 292 (unsigned long) row); 293 break; 294 } 295 if (swab) /* Swap bytes if needed */ 296 swapBytesInScanline(buf, width, dtype); 297 for (col = 0; col < width; col++) 298 memcpy(buf1 + (col*nbands+band)*depth, 299 buf + col * depth, depth); 300 } 301 break; 302 case PIXEL: /* pixel interleaved data */ 303 default: 304 if (read(fd, buf1, bufsize) < 0) { 305 fprintf(stderr, 306 "%s: %s: scanline %lu: Read error.\n", 307 argv[0], argv[optind], 308 (unsigned long) row); 309 break; 310 } 311 if (swab) /* Swap bytes if needed */ 312 swapBytesInScanline(buf1, width, dtype); 313 break; 314 } 315 316 if (TIFFWriteScanline(out, buf1, row, 0) < 0) { 317 fprintf(stderr, "%s: %s: scanline %lu: Write error.\n", 318 argv[0], outfilename, (unsigned long) row); 319 break; 320 } 321 } 322 if (buf) 323 _TIFFfree(buf); 324 if (buf1) 325 _TIFFfree(buf1); 326 TIFFClose(out); 327 return (0); 328} 329 330static void 331swapBytesInScanline(void *buf, uint32 width, TIFFDataType dtype) 332{ 333 switch (dtype) { 334 case TIFF_SHORT: 335 case TIFF_SSHORT: 336 TIFFSwabArrayOfShort((uint16*)buf, 337 (unsigned long)width); 338 break; 339 case TIFF_LONG: 340 case TIFF_SLONG: 341 TIFFSwabArrayOfLong((uint32*)buf, 342 (unsigned long)width); 343 break; 344 /* case TIFF_FLOAT: */ /* FIXME */ 345 case TIFF_DOUBLE: 346 TIFFSwabArrayOfDouble((double*)buf, 347 (unsigned long)width); 348 break; 349 default: 350 break; 351 } 352} 353 354static int 355guessSize(int fd, TIFFDataType dtype, off_t hdr_size, uint32 nbands, 356 int swab, uint32 *width, uint32 *length) 357{ 358 const float longt = 40.0; /* maximum possible height/width ratio */ 359 char *buf1, *buf2; 360 struct stat filestat; 361 uint32 w, h, scanlinesize, imagesize; 362 uint32 depth = TIFFDataWidth(dtype); 363 float cor_coef = 0, tmp; 364 365 fstat(fd, &filestat); 366 367 if (filestat.st_size < hdr_size) { 368 fprintf(stderr, "Too large header size specified.\n"); 369 return -1; 370 } 371 372 imagesize = (filestat.st_size - hdr_size) / nbands / depth; 373 374 if (*width != 0 && *length == 0) { 375 fprintf(stderr, "Image height is not specified.\n"); 376 377 *length = imagesize / *width; 378 379 fprintf(stderr, "Height is guessed as %lu.\n", 380 (unsigned long)*length); 381 382 return 1; 383 } else if (*width == 0 && *length != 0) { 384 fprintf(stderr, "Image width is not specified.\n"); 385 386 *width = imagesize / *length; 387 388 fprintf(stderr, "Width is guessed as %lu.\n", 389 (unsigned long)*width); 390 391 return 1; 392 } else if (*width == 0 && *length == 0) { 393 fprintf(stderr, "Image width and height are not specified.\n"); 394 395 for (w = (uint32) sqrt(imagesize / longt); 396 w < sqrt(imagesize * longt); 397 w++) { 398 if (imagesize % w == 0) { 399 scanlinesize = w * depth; 400 buf1 = _TIFFmalloc(scanlinesize); 401 buf2 = _TIFFmalloc(scanlinesize); 402 h = imagesize / w; 403 lseek(fd, hdr_size + (int)(h/2)*scanlinesize, 404 SEEK_SET); 405 read(fd, buf1, scanlinesize); 406 read(fd, buf2, scanlinesize); 407 if (swab) { 408 swapBytesInScanline(buf1, w, dtype); 409 swapBytesInScanline(buf2, w, dtype); 410 } 411 tmp = (float) fabs(correlation(buf1, buf2, 412 w, dtype)); 413 if (tmp > cor_coef) { 414 cor_coef = tmp; 415 *width = w, *length = h; 416 } 417 418 _TIFFfree(buf1); 419 _TIFFfree(buf2); 420 } 421 } 422 423 fprintf(stderr, 424 "Width is guessed as %lu, height is guessed as %lu.\n", 425 (unsigned long)*width, (unsigned long)*length); 426 427 return 1; 428 } else { 429 if (filestat.st_size<(off_t)(hdr_size+(*width)*(*length)*nbands*depth)) { 430 fprintf(stderr, "Input file too small.\n"); 431 return -1; 432 } 433 } 434 435 return 1; 436} 437 438/* Calculate correlation coefficient between two numeric vectors */ 439static double 440correlation(void *buf1, void *buf2, uint32 n_elem, TIFFDataType dtype) 441{ 442 double X, Y, M1 = 0.0, M2 = 0.0, D1 = 0.0, D2 = 0.0, K = 0.0; 443 uint32 i; 444 445 switch (dtype) { 446 case TIFF_BYTE: 447 default: 448 for (i = 0; i < n_elem; i++) { 449 X = ((unsigned char *)buf1)[i]; 450 Y = ((unsigned char *)buf2)[i]; 451 M1 += X, M2 += Y; 452 D1 += X * X, D2 += Y * Y; 453 K += X * Y; 454 } 455 break; 456 case TIFF_SBYTE: 457 for (i = 0; i < n_elem; i++) { 458 X = ((signed char *)buf1)[i]; 459 Y = ((signed char *)buf2)[i]; 460 M1 += X, M2 += Y; 461 D1 += X * X, D2 += Y * Y; 462 K += X * Y; 463 } 464 break; 465 case TIFF_SHORT: 466 for (i = 0; i < n_elem; i++) { 467 X = ((uint16 *)buf1)[i]; 468 Y = ((uint16 *)buf2)[i]; 469 M1 += X, M2 += Y; 470 D1 += X * X, D2 += Y * Y; 471 K += X * Y; 472 } 473 break; 474 case TIFF_SSHORT: 475 for (i = 0; i < n_elem; i++) { 476 X = ((int16 *)buf1)[i]; 477 Y = ((int16 *)buf2)[i]; 478 M1 += X, M2 += Y; 479 D1 += X * X, D2 += Y * Y; 480 K += X * Y; 481 } 482 break; 483 case TIFF_LONG: 484 for (i = 0; i < n_elem; i++) { 485 X = ((uint32 *)buf1)[i]; 486 Y = ((uint32 *)buf2)[i]; 487 M1 += X, M2 += Y; 488 D1 += X * X, D2 += Y * Y; 489 K += X * Y; 490 } 491 break; 492 case TIFF_SLONG: 493 for (i = 0; i < n_elem; i++) { 494 X = ((int32 *)buf1)[i]; 495 Y = ((int32 *)buf2)[i]; 496 M1 += X, M2 += Y; 497 D1 += X * X, D2 += Y * Y; 498 K += X * Y; 499 } 500 break; 501 case TIFF_FLOAT: 502 for (i = 0; i < n_elem; i++) { 503 X = ((float *)buf1)[i]; 504 Y = ((float *)buf2)[i]; 505 M1 += X, M2 += Y; 506 D1 += X * X, D2 += Y * Y; 507 K += X * Y; 508 } 509 break; 510 case TIFF_DOUBLE: 511 for (i = 0; i < n_elem; i++) { 512 X = ((double *)buf1)[i]; 513 Y = ((double *)buf2)[i]; 514 M1 += X, M2 += Y; 515 D1 += X * X, D2 += Y * Y; 516 K += X * Y; 517 } 518 break; 519 } 520 521 M1 /= n_elem; 522 M2 /= n_elem; 523 D1 -= M1 * M1 * n_elem; 524 D2 -= M2 * M2 * n_elem; 525 K = (K - M1 * M2 * n_elem) / sqrt(D1 * D2); 526 527 return K; 528} 529 530static int 531processCompressOptions(char* opt) 532{ 533 if (strcmp(opt, "none") == 0) 534 compression = COMPRESSION_NONE; 535 else if (strcmp(opt, "packbits") == 0) 536 compression = COMPRESSION_PACKBITS; 537 else if (strncmp(opt, "jpeg", 4) == 0) { 538 char* cp = strchr(opt, ':'); 539 540 compression = COMPRESSION_JPEG; 541 while( cp ) 542 { 543 if (isdigit((int)cp[1])) 544 quality = atoi(cp+1); 545 else if (cp[1] == 'r' ) 546 jpegcolormode = JPEGCOLORMODE_RAW; 547 else 548 usage(); 549 550 cp = strchr(cp+1,':'); 551 } 552 } else if (strncmp(opt, "lzw", 3) == 0) { 553 char* cp = strchr(opt, ':'); 554 if (cp) 555 predictor = atoi(cp+1); 556 compression = COMPRESSION_LZW; 557 } else if (strncmp(opt, "zip", 3) == 0) { 558 char* cp = strchr(opt, ':'); 559 if (cp) 560 predictor = atoi(cp+1); 561 compression = COMPRESSION_DEFLATE; 562 } else 563 return (0); 564 return (1); 565} 566 567static char* stuff[] = { 568"raw2tiff --- tool for converting raw byte sequences in TIFF images", 569"usage: raw2tiff [options] input.raw output.tif", 570"where options are:", 571" -L input data has LSB2MSB bit order (default)", 572" -M input data has MSB2LSB bit order", 573" -r # make each strip have no more than # rows", 574" -H # size of input image file header in bytes (0 by default)", 575" -w # width of input image in pixels", 576" -l # length of input image in lines", 577" -b # number of bands in input image (1 by default)", 578"", 579" -d data_type type of samples in input image", 580"where data_type may be:", 581" byte 8-bit unsigned integer (default)", 582" short 16-bit unsigned integer", 583" long 32-bit unsigned integer", 584" sbyte 8-bit signed integer", 585" sshort 16-bit signed integer", 586" slong 32-bit signed integer", 587" float 32-bit IEEE floating point", 588" double 64-bit IEEE floating point", 589"", 590" -p photo photometric interpretation (color space) of the input image", 591"where photo may be:", 592" miniswhite white color represented with 0 value", 593" minisblack black color represented with 0 value (default)", 594" rgb image has RGB color model", 595" cmyk image has CMYK (separated) color model", 596" ycbcr image has YCbCr color model", 597" cielab image has CIE L*a*b color model", 598" icclab image has ICC L*a*b color model", 599" itulab image has ITU L*a*b color model", 600"", 601" -s swap bytes fetched from input file", 602"", 603" -i config type of samples interleaving in input image", 604"where config may be:", 605" pixel pixel interleaved data (default)", 606" band band interleaved data", 607"", 608" -c lzw[:opts] compress output with Lempel-Ziv & Welch encoding", 609" -c zip[:opts] compress output with deflate encoding", 610" -c jpeg[:opts] compress output with JPEG encoding", 611" -c packbits compress output with packbits encoding", 612" -c none use no compression algorithm on output", 613"", 614"JPEG options:", 615" # set compression quality level (0-100, default 75)", 616" r output color image as RGB rather than YCbCr", 617"For example, -c jpeg:r:50 to get JPEG-encoded RGB data with 50% comp. quality", 618"", 619"LZW and deflate options:", 620" # set predictor value", 621"For example, -c lzw:2 to get LZW-encoded data with horizontal differencing", 622" -o out.tif write output to out.tif", 623" -h this help message", 624NULL 625}; 626 627static void 628usage(void) 629{ 630 char buf[BUFSIZ]; 631 int i; 632 633 setbuf(stderr, buf); 634 fprintf(stderr, "%s\n\n", TIFFGetVersion()); 635 for (i = 0; stuff[i] != NULL; i++) 636 fprintf(stderr, "%s\n", stuff[i]); 637 exit(-1); 638} 639 640/* vim: set ts=8 sts=8 sw=8 noet: */ 641/* 642 * Local Variables: 643 * mode: c 644 * c-basic-offset: 8 645 * fill-column: 78 646 * End: 647 */ 648