3  * Project:  libtiff tools 
   4  * Purpose:  Convert raw byte sequences in TIFF images 
   5  * Author:   Andrey Kiselev, dron@ak4719.spb.edu 
   7  ****************************************************************************** 
   8  * Copyright (c) 2002, Andrey Kiselev <dron@ak4719.spb.edu> 
  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. 
  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.   
  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  
  30 #include "tif_config.h" 
  36 #include <sys/types.h> 
  49 # include <sys/types.h> 
  59 extern int getopt(int, char**, char*); 
  71 static  uint16 compression 
= (uint16
) -1; 
  72 static  int jpegcolormode 
= JPEGCOLORMODE_RGB
; 
  73 static  int quality 
= 75;               /* JPEG quality */ 
  74 static  uint16 predictor 
= 0; 
  76 static void swapBytesInScanline(void *, uint32
, TIFFDataType
); 
  77 static int guessSize(int, TIFFDataType
, off_t
, uint32
, int, 
  79 static double correlation(void *, void *, uint32
, TIFFDataType
); 
  80 static void usage(void); 
  81 static  int processCompressOptions(char*); 
  84 main(int argc
, char* argv
[]) 
  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
; 
  98         char    *outfilename 
= NULL
; 
 101         uint32 row
, col
, band
; 
 103         unsigned char *buf 
= NULL
, *buf1 
= NULL
; 
 107         while ((c 
= getopt(argc
, argv
, "c:r:H:w:l:b:d:LMp:si:o:h")) != -1) { 
 109                 case 'c':               /* compression scheme */ 
 110                         if (!processCompressOptions(optarg
)) 
 113                 case 'r':               /* rows/strip */ 
 114                         rowsperstrip 
= atoi(optarg
); 
 116                 case 'H':               /* size of input image file header */ 
 117                         hdr_size 
= atoi(optarg
); 
 119                 case 'w':               /* input image width */ 
 120                         width 
= atoi(optarg
); 
 122                 case 'l':               /* input image length */ 
 123                         length 
= atoi(optarg
); 
 125                 case 'b':               /* number of bands in input image */ 
 126                         nbands 
= atoi(optarg
); 
 128                 case 'd':               /* type of samples in input image */ 
 129                         if (strncmp(optarg
, "byte", 4) == 0) 
 131                         else if (strncmp(optarg
, "short", 5) == 0) 
 133                         else if  (strncmp(optarg
, "long", 4) == 0) 
 135                         else if  (strncmp(optarg
, "sbyte", 5) == 0) 
 137                         else if  (strncmp(optarg
, "sshort", 6) == 0) 
 139                         else if  (strncmp(optarg
, "slong", 5) == 0) 
 141                         else if  (strncmp(optarg
, "float", 5) == 0) 
 143                         else if  (strncmp(optarg
, "double", 6) == 0) 
 147                         depth 
= TIFFDataWidth(dtype
); 
 149                 case 'L':               /* input has lsb-to-msb fillorder */ 
 150                         fillorder 
= FILLORDER_LSB2MSB
; 
 152                 case 'M':               /* input has msb-to-lsb fillorder */ 
 153                         fillorder 
= FILLORDER_MSB2LSB
; 
 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
; 
 173                                 photometric 
= PHOTOMETRIC_MINISBLACK
; 
 175                 case 's':               /* do we need to swap bytes? */ 
 178                 case 'i':               /* type of interleaving */ 
 179                         if (strncmp(optarg
, "pixel", 4) == 0) 
 180                                 interleaving 
= PIXEL
; 
 181                         else if  (strncmp(optarg
, "band", 6) == 0) 
 187                         outfilename 
= optarg
; 
 196         if (argc 
- optind 
< 2) 
 199         fd 
= open(argv
[optind
], O_RDONLY
|O_BINARY
, 0); 
 201                 fprintf(stderr
, "%s: %s: Cannot open input file.\n", 
 202                         argv
[0], argv
[optind
]); 
 206         if (guessSize(fd
, dtype
, hdr_size
, nbands
, swab
, &width
, &length
) < 0) 
 209         if (outfilename 
== NULL
) 
 210                 outfilename 
= argv
[optind
+1]; 
 211         out 
= TIFFOpen(outfilename
, "w"); 
 213                 fprintf(stderr
, "%s: %s: Cannot open file for output.\n", 
 214                         argv
[0], outfilename
); 
 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
); 
 229                 TIFFSetField(out
, TIFFTAG_SAMPLEFORMAT
, SAMPLEFORMAT_UINT
); 
 234                 TIFFSetField(out
, TIFFTAG_SAMPLEFORMAT
, SAMPLEFORMAT_INT
); 
 238                 TIFFSetField(out
, TIFFTAG_SAMPLEFORMAT
, SAMPLEFORMAT_IEEEFP
); 
 241                 TIFFSetField(out
, TIFFTAG_SAMPLEFORMAT
, SAMPLEFORMAT_VOID
); 
 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
); 
 255         case COMPRESSION_LZW
: 
 256         case COMPRESSION_DEFLATE
: 
 258                         TIFFSetField(out
, TIFFTAG_PREDICTOR
, predictor
); 
 261         switch(interleaving
) { 
 262         case BAND
:                              /* band interleaved data */ 
 263                 linebytes 
= width 
* depth
; 
 264                 buf 
= (unsigned char *)_TIFFmalloc(linebytes
); 
 266         case PIXEL
:                             /* pixel interleaved data */ 
 268                 linebytes 
= width 
* nbands 
* depth
; 
 271         bufsize 
= width 
* nbands 
* depth
; 
 272         buf1 
= (unsigned char *)_TIFFmalloc(bufsize
); 
 274         rowsperstrip 
= TIFFDefaultStripSize(out
, rowsperstrip
); 
 275         if (rowsperstrip 
> length
) { 
 276                 rowsperstrip 
= length
; 
 278         TIFFSetField(out
, TIFFTAG_ROWSPERSTRIP
, rowsperstrip 
); 
 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
++) { 
 286                                       hdr_size 
+ (length
*band
+row
)*linebytes
, 
 288                                 if (read(fd
, buf
, linebytes
) < 0) { 
 290                                         "%s: %s: scanline %lu: Read error.\n", 
 291                                         argv
[0], argv
[optind
], 
 292                                         (unsigned long) row
); 
 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
); 
 302                 case PIXEL
:                     /* pixel interleaved data */ 
 304                         if (read(fd
, buf1
, bufsize
) < 0) { 
 306                                         "%s: %s: scanline %lu: Read error.\n", 
 307                                         argv
[0], argv
[optind
], 
 308                                         (unsigned long) row
); 
 311                         if (swab
)               /* Swap bytes if needed */ 
 312                                 swapBytesInScanline(buf1
, width
, dtype
); 
 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
); 
 331 swapBytesInScanline(void *buf
, uint32 width
, TIFFDataType dtype
) 
 336                         TIFFSwabArrayOfShort((uint16
*)buf
, 
 337                                              (unsigned long)width
); 
 341                         TIFFSwabArrayOfLong((uint32
*)buf
, 
 342                                             (unsigned long)width
); 
 344                 /* case TIFF_FLOAT: */  /* FIXME */ 
 346                         TIFFSwabArrayOfDouble((double*)buf
, 
 347                                               (unsigned long)width
); 
 355 guessSize(int fd
, TIFFDataType dtype
, off_t hdr_size
, uint32 nbands
, 
 356           int swab
, uint32 
*width
, uint32 
*length
) 
 358         const float longt 
= 40.0;    /* maximum possible height/width ratio */ 
 360         struct stat filestat
; 
 361         uint32      w
, h
, scanlinesize
, imagesize
; 
 362         uint32      depth 
= TIFFDataWidth(dtype
); 
 363         float       cor_coef 
= 0, tmp
; 
 365         fstat(fd
, &filestat
); 
 367         if (filestat
.st_size 
< hdr_size
) { 
 368                 fprintf(stderr
, "Too large header size specified.\n"); 
 372         imagesize 
= (filestat
.st_size 
- hdr_size
) / nbands 
/ depth
; 
 374         if (*width 
!= 0 && *length 
== 0) { 
 375                 fprintf(stderr
, "Image height is not specified.\n"); 
 377                 *length 
= imagesize 
/ *width
; 
 379                 fprintf(stderr
, "Height is guessed as %lu.\n", 
 380                         (unsigned long)*length
); 
 383         } else if (*width 
== 0 && *length 
!= 0) { 
 384                 fprintf(stderr
, "Image width is not specified.\n"); 
 386                 *width 
= imagesize 
/ *length
; 
 388                 fprintf(stderr
, "Width is guessed as %lu.\n", 
 389                         (unsigned long)*width
); 
 392         } else if (*width 
== 0 && *length 
== 0) { 
 393                 fprintf(stderr
, "Image width and height are not specified.\n"); 
 395                 for (w 
= (uint32
) sqrt(imagesize 
/ longt
); 
 396                      w 
< sqrt(imagesize 
* longt
); 
 398                         if (imagesize 
% w 
== 0) { 
 399                                 scanlinesize 
= w 
* depth
; 
 400                                 buf1 
= _TIFFmalloc(scanlinesize
); 
 401                                 buf2 
= _TIFFmalloc(scanlinesize
); 
 403                                 lseek(fd
, hdr_size 
+ (int)(h
/2)*scanlinesize
, 
 405                                 read(fd
, buf1
, scanlinesize
); 
 406                                 read(fd
, buf2
, scanlinesize
); 
 408                                         swapBytesInScanline(buf1
, w
, dtype
); 
 409                                         swapBytesInScanline(buf2
, w
, dtype
); 
 411                                 tmp 
= (float) fabs(correlation(buf1
, buf2
, 
 413                                 if (tmp 
> cor_coef
) { 
 415                                         *width 
= w
, *length 
= h
; 
 424                         "Width is guessed as %lu, height is guessed as %lu.\n", 
 425                         (unsigned long)*width
, (unsigned long)*length
); 
 429                 if (filestat
.st_size
<(off_t
)(hdr_size
+(*width
)*(*length
)*nbands
*depth
)) { 
 430                         fprintf(stderr
, "Input file too small.\n"); 
 438 /* Calculate correlation coefficient between two numeric vectors */ 
 440 correlation(void *buf1
, void *buf2
, uint32 n_elem
, TIFFDataType dtype
) 
 442         double  X
, Y
, M1 
= 0.0, M2 
= 0.0, D1 
= 0.0, D2 
= 0.0, K 
= 0.0; 
 448                         for (i 
= 0; i 
< n_elem
; i
++) { 
 449                                 X 
= ((unsigned char *)buf1
)[i
]; 
 450                                 Y 
= ((unsigned char *)buf2
)[i
]; 
 452                                 D1 
+= X 
* X
, D2 
+= Y 
* Y
; 
 457                         for (i 
= 0; i 
< n_elem
; i
++) { 
 458                                 X 
= ((signed char *)buf1
)[i
]; 
 459                                 Y 
= ((signed char *)buf2
)[i
]; 
 461                                 D1 
+= X 
* X
, D2 
+= Y 
* Y
; 
 466                         for (i 
= 0; i 
< n_elem
; i
++) { 
 467                                 X 
= ((uint16 
*)buf1
)[i
]; 
 468                                 Y 
= ((uint16 
*)buf2
)[i
]; 
 470                                 D1 
+= X 
* X
, D2 
+= Y 
* Y
; 
 475                         for (i 
= 0; i 
< n_elem
; i
++) { 
 476                                 X 
= ((int16 
*)buf1
)[i
]; 
 477                                 Y 
= ((int16 
*)buf2
)[i
]; 
 479                                 D1 
+= X 
* X
, D2 
+= Y 
* Y
; 
 484                         for (i 
= 0; i 
< n_elem
; i
++) { 
 485                                 X 
= ((uint32 
*)buf1
)[i
]; 
 486                                 Y 
= ((uint32 
*)buf2
)[i
]; 
 488                                 D1 
+= X 
* X
, D2 
+= Y 
* Y
; 
 493                         for (i 
= 0; i 
< n_elem
; i
++) { 
 494                                 X 
= ((int32 
*)buf1
)[i
]; 
 495                                 Y 
= ((int32 
*)buf2
)[i
]; 
 497                                 D1 
+= X 
* X
, D2 
+= Y 
* Y
; 
 502                         for (i 
= 0; i 
< n_elem
; i
++) { 
 503                                 X 
= ((float *)buf1
)[i
]; 
 504                                 Y 
= ((float *)buf2
)[i
]; 
 506                                 D1 
+= X 
* X
, D2 
+= Y 
* Y
; 
 511                         for (i 
= 0; i 
< n_elem
; i
++) { 
 512                                 X 
= ((double *)buf1
)[i
]; 
 513                                 Y 
= ((double *)buf2
)[i
]; 
 515                                 D1 
+= X 
* X
, D2 
+= Y 
* Y
; 
 523         D1 
-= M1 
* M1 
* n_elem
; 
 524         D2 
-= M2 
* M2 
* n_elem
; 
 525         K 
= (K 
- M1 
* M2 
* n_elem
) / sqrt(D1 
* D2
); 
 531 processCompressOptions(char* opt
) 
 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
, ':'); 
 540                 compression 
= COMPRESSION_JPEG
; 
 543                     if (isdigit((int)cp
[1])) 
 544                         quality 
= atoi(cp
+1); 
 545                     else if (cp
[1] == 'r' ) 
 546                         jpegcolormode 
= JPEGCOLORMODE_RAW
; 
 550                     cp 
= strchr(cp
+1,':'); 
 552         } else if (strncmp(opt
, "lzw", 3) == 0) { 
 553                 char* cp 
= strchr(opt
, ':'); 
 555                         predictor 
= atoi(cp
+1); 
 556                 compression 
= COMPRESSION_LZW
; 
 557         } else if (strncmp(opt
, "zip", 3) == 0) { 
 558                 char* cp 
= strchr(opt
, ':'); 
 560                         predictor 
= atoi(cp
+1); 
 561                 compression 
= COMPRESSION_DEFLATE
; 
 567 static 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)", 
 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", 
 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", 
 601 " -s            swap bytes fetched from input file", 
 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", 
 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", 
 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", 
 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", 
 634         fprintf(stderr
, "%s\n\n", TIFFGetVersion()); 
 635         for (i 
= 0; stuff
[i
] != NULL
; i
++) 
 636                 fprintf(stderr
, "%s\n", stuff
[i
]); 
 640 /* vim: set ts=8 sts=8 sw=8 noet: */