2 * Project
: libtiff tools
3 * Purpose
: Convert raw byte sequences in TIFF images
4 * Author
: Andrey Kiselev
, dron@ak4719
.spb
.edu
6 ******************************************************************************
7 * Copyright (c
) 2002, Andrey Kiselev
<dron@ak4719
.spb
.edu
>
9 * Permission to use
, copy
, modify
, distribute
, and sell
this software
and
10 * its documentation
for any purpose is hereby granted without fee
, provided
11 * that (i
) the above copyright notices
and this permission notice appear in
12 * all copies of the software
and related documentation
, and (ii
) the names of
13 * Sam Leffler
and Silicon Graphics may
not be used in any advertising
or
14 * publicity relating to the software without the specific
, prior written
15 * permission of Sam Leffler
and Silicon Graphics
.
17 * THE SOFTWARE IS PROVIDED
"AS-IS" AND WITHOUT WARRANTY OF ANY KIND
,
18 * EXPRESS
, IMPLIED OR OTHERWISE
, INCLUDING WITHOUT LIMITATION
, ANY
19 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
.
21 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
22 * ANY SPECIAL
, INCIDENTAL
, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND
,
23 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE
, DATA OR PROFITS
,
24 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE
, AND ON ANY THEORY OF
25 * LIABILITY
, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
29 #include "tif_config.h"
35 #include <sys/types.h>
48 # include <sys/types.h>
62 extern int getopt(int, char**, char*);
74 static uint16 compression
= (uint16
) -1;
75 static int jpegcolormode
= JPEGCOLORMODE_RGB
;
76 static int quality
= 75; /* JPEG quality */
77 static uint16 predictor
= 0;
79 static void swapBytesInScanline(void *, uint32
, TIFFDataType
);
80 static int guessSize(int, TIFFDataType
, off_t
, uint32
, int,
82 static double correlation(void *, void *, uint32
, TIFFDataType
);
83 static void usage(void);
84 static int processCompressOptions(char*);
87 main(int argc
, char* argv
[])
89 uint32 width
= 0, length
= 0, linebytes
, bufsize
;
90 uint32 nbands
= 1; /* number of bands in input image*/
91 off_t hdr_size
= 0; /* size of the header to skip */
92 TIFFDataType dtype
= TIFF_BYTE
;
93 int16 depth
= 1; /* bytes per pixel in input image */
94 int swab
= 0; /* byte swapping flag */
95 InterleavingType interleaving
= 0; /* interleaving type flag */
96 uint32 rowsperstrip
= (uint32
) -1;
97 uint16 photometric
= PHOTOMETRIC_MINISBLACK
;
98 uint16 config
= PLANARCONFIG_CONTIG
;
99 uint16 fillorder
= FILLORDER_LSB2MSB
;
101 char *outfilename
= NULL
;
104 uint32 row
, col
, band
;
106 unsigned char *buf
= NULL
, *buf1
= NULL
;
110 while ((c
= getopt(argc
, argv
, "c:r:H:w:l:b:d:LMp:si:o:h")) != -1) {
112 case 'c': /* compression scheme */
113 if (!processCompressOptions(optarg
))
116 case 'r': /* rows/strip */
117 rowsperstrip
= atoi(optarg
);
119 case 'H': /* size of input image file header */
120 hdr_size
= atoi(optarg
);
122 case 'w': /* input image width */
123 width
= atoi(optarg
);
125 case 'l': /* input image length */
126 length
= atoi(optarg
);
128 case 'b': /* number of bands in input image */
129 nbands
= atoi(optarg
);
131 case 'd': /* type of samples in input image */
132 if (strncmp(optarg
, "byte", 4) == 0)
134 else if (strncmp(optarg
, "short", 5) == 0)
136 else if (strncmp(optarg
, "long", 4) == 0)
138 else if (strncmp(optarg
, "sbyte", 5) == 0)
140 else if (strncmp(optarg
, "sshort", 6) == 0)
142 else if (strncmp(optarg
, "slong", 5) == 0)
144 else if (strncmp(optarg
, "float", 5) == 0)
146 else if (strncmp(optarg
, "double", 6) == 0)
150 depth
= TIFFDataWidth(dtype
);
152 case 'L': /* input has lsb-to-msb fillorder */
153 fillorder
= FILLORDER_LSB2MSB
;
155 case 'M': /* input has msb-to-lsb fillorder */
156 fillorder
= FILLORDER_MSB2LSB
;
158 case 'p': /* photometric interpretation */
159 if (strncmp(optarg
, "miniswhite", 10) == 0)
160 photometric
= PHOTOMETRIC_MINISWHITE
;
161 else if (strncmp(optarg
, "minisblack", 10) == 0)
162 photometric
= PHOTOMETRIC_MINISBLACK
;
163 else if (strncmp(optarg
, "rgb", 3) == 0)
164 photometric
= PHOTOMETRIC_RGB
;
165 else if (strncmp(optarg
, "cmyk", 4) == 0)
166 photometric
= PHOTOMETRIC_SEPARATED
;
167 else if (strncmp(optarg
, "ycbcr", 5) == 0)
168 photometric
= PHOTOMETRIC_YCBCR
;
169 else if (strncmp(optarg
, "cielab", 6) == 0)
170 photometric
= PHOTOMETRIC_CIELAB
;
171 else if (strncmp(optarg
, "icclab", 6) == 0)
172 photometric
= PHOTOMETRIC_ICCLAB
;
173 else if (strncmp(optarg
, "itulab", 6) == 0)
174 photometric
= PHOTOMETRIC_ITULAB
;
176 photometric
= PHOTOMETRIC_MINISBLACK
;
178 case 's': /* do we need to swap bytes? */
181 case 'i': /* type of interleaving */
182 if (strncmp(optarg
, "pixel", 4) == 0)
183 interleaving
= PIXEL
;
184 else if (strncmp(optarg
, "band", 6) == 0)
190 outfilename
= optarg
;
199 if (argc
- optind
< 2)
202 fd
= open(argv
[optind
], O_RDONLY
|O_BINARY
, 0);
204 fprintf(stderr
, "%s: %s: Cannot open input file.\n",
205 argv
[0], argv
[optind
]);
209 if (guessSize(fd
, dtype
, hdr_size
, nbands
, swab
, &width
, &length
) < 0)
212 if (outfilename
== NULL
)
213 outfilename
= argv
[optind
+1];
214 out
= TIFFOpen(outfilename
, "w");
216 fprintf(stderr
, "%s: %s: Cannot open file for output.\n",
217 argv
[0], outfilename
);
220 TIFFSetField(out
, TIFFTAG_IMAGEWIDTH
, width
);
221 TIFFSetField(out
, TIFFTAG_IMAGELENGTH
, length
);
222 TIFFSetField(out
, TIFFTAG_ORIENTATION
, ORIENTATION_TOPLEFT
);
223 TIFFSetField(out
, TIFFTAG_SAMPLESPERPIXEL
, nbands
);
224 TIFFSetField(out
, TIFFTAG_BITSPERSAMPLE
, depth
* 8);
225 TIFFSetField(out
, TIFFTAG_FILLORDER
, fillorder
);
226 TIFFSetField(out
, TIFFTAG_PLANARCONFIG
, config
);
227 TIFFSetField(out
, TIFFTAG_PHOTOMETRIC
, photometric
);
232 TIFFSetField(out
, TIFFTAG_SAMPLEFORMAT
, SAMPLEFORMAT_UINT
);
237 TIFFSetField(out
, TIFFTAG_SAMPLEFORMAT
, SAMPLEFORMAT_INT
);
241 TIFFSetField(out
, TIFFTAG_SAMPLEFORMAT
, SAMPLEFORMAT_IEEEFP
);
244 TIFFSetField(out
, TIFFTAG_SAMPLEFORMAT
, SAMPLEFORMAT_VOID
);
247 if (compression
== (uint16
) -1)
248 compression
= COMPRESSION_PACKBITS
;
249 TIFFSetField(out
, TIFFTAG_COMPRESSION
, compression
);
250 switch (compression
) {
251 case COMPRESSION_JPEG
:
252 if (photometric
== PHOTOMETRIC_RGB
253 && jpegcolormode
== JPEGCOLORMODE_RGB
)
254 photometric
= PHOTOMETRIC_YCBCR
;
255 TIFFSetField(out
, TIFFTAG_JPEGQUALITY
, quality
);
256 TIFFSetField(out
, TIFFTAG_JPEGCOLORMODE
, jpegcolormode
);
258 case COMPRESSION_LZW
:
259 case COMPRESSION_DEFLATE
:
261 TIFFSetField(out
, TIFFTAG_PREDICTOR
, predictor
);
264 switch(interleaving
) {
265 case BAND
: /* band interleaved data */
266 linebytes
= width
* depth
;
267 buf
= (unsigned char *)_TIFFmalloc(linebytes
);
269 case PIXEL
: /* pixel interleaved data */
271 linebytes
= width
* nbands
* depth
;
274 bufsize
= width
* nbands
* depth
;
275 buf1
= (unsigned char *)_TIFFmalloc(bufsize
);
277 rowsperstrip
= TIFFDefaultStripSize(out
, rowsperstrip
);
278 if (rowsperstrip
> length
) {
279 rowsperstrip
= length
;
281 TIFFSetField(out
, TIFFTAG_ROWSPERSTRIP
, rowsperstrip
);
283 lseek(fd
, hdr_size
, SEEK_SET
); /* Skip the file header */
284 for (row
= 0; row
< length
; row
++) {
285 switch(interleaving
) {
286 case BAND
: /* band interleaved data */
287 for (band
= 0; band
< nbands
; band
++) {
289 hdr_size
+ (length
*band
+row
)*linebytes
,
291 if (read(fd
, buf
, linebytes
) < 0) {
293 "%s: %s: scanline %lu: Read error.\n",
294 argv
[0], argv
[optind
],
295 (unsigned long) row
);
298 if (swab
) /* Swap bytes if needed */
299 swapBytesInScanline(buf
, width
, dtype
);
300 for (col
= 0; col
< width
; col
++)
301 memcpy(buf1
+ (col
*nbands
+band
)*depth
,
302 buf
+ col
* depth
, depth
);
305 case PIXEL
: /* pixel interleaved data */
307 if (read(fd
, buf1
, bufsize
) < 0) {
309 "%s: %s: scanline %lu: Read error.\n",
310 argv
[0], argv
[optind
],
311 (unsigned long) row
);
314 if (swab
) /* Swap bytes if needed */
315 swapBytesInScanline(buf1
, width
, dtype
);
319 if (TIFFWriteScanline(out
, buf1
, row
, 0) < 0) {
320 fprintf(stderr
, "%s: %s: scanline %lu: Write error.\n",
321 argv
[0], outfilename
, (unsigned long) row
);
334 swapBytesInScanline(void *buf
, uint32 width
, TIFFDataType dtype
)
339 TIFFSwabArrayOfShort((uint16
*)buf
,
340 (unsigned long)width
);
344 TIFFSwabArrayOfLong((uint32
*)buf
,
345 (unsigned long)width
);
347 /* case TIFF_FLOAT: */ /* FIXME */
349 TIFFSwabArrayOfDouble((double*)buf
,
350 (unsigned long)width
);
358 guessSize(int fd
, TIFFDataType dtype
, off_t hdr_size
, uint32 nbands
,
359 int swab
, uint32
*width
, uint32
*length
)
361 const float longt
= 40.0; /* maximum possible height/width ratio */
363 struct stat filestat
;
364 uint32 w
, h
, scanlinesize
, imagesize
;
365 uint32 depth
= TIFFDataWidth(dtype
);
366 float cor_coef
= 0, tmp
;
368 fstat(fd
, &filestat
);
370 if (filestat
.st_size
< hdr_size
) {
371 fprintf(stderr
, "Too large header size specified.\n");
375 imagesize
= (filestat
.st_size
- hdr_size
) / nbands
/ depth
;
377 if (*width
!= 0 && *length
== 0) {
378 fprintf(stderr
, "Image height is not specified.\n");
380 *length
= imagesize
/ *width
;
382 fprintf(stderr
, "Height is guessed as %lu.\n",
383 (unsigned long)*length
);
386 } else if (*width
== 0 && *length
!= 0) {
387 fprintf(stderr
, "Image width is not specified.\n");
389 *width
= imagesize
/ *length
;
391 fprintf(stderr
, "Width is guessed as %lu.\n",
392 (unsigned long)*width
);
395 } else if (*width
== 0 && *length
== 0) {
396 fprintf(stderr
, "Image width and height are not specified.\n");
398 for (w
= (uint32
) sqrt(imagesize
/ longt
);
399 w
< sqrt(imagesize
* longt
);
401 if (imagesize
% w
== 0) {
402 scanlinesize
= w
* depth
;
403 buf1
= _TIFFmalloc(scanlinesize
);
404 buf2
= _TIFFmalloc(scanlinesize
);
406 lseek(fd
, hdr_size
+ (int)(h
/2)*scanlinesize
,
408 read(fd
, buf1
, scanlinesize
);
409 read(fd
, buf2
, scanlinesize
);
411 swapBytesInScanline(buf1
, w
, dtype
);
412 swapBytesInScanline(buf2
, w
, dtype
);
414 tmp
= (float) fabs(correlation(buf1
, buf2
,
416 if (tmp
> cor_coef
) {
418 *width
= w
, *length
= h
;
427 "Width is guessed as %lu, height is guessed as %lu.\n",
428 (unsigned long)*width
, (unsigned long)*length
);
432 if (filestat
.st_size
<(off_t
)(hdr_size
+(*width
)*(*length
)*nbands
*depth
)) {
433 fprintf(stderr
, "Input file too small.\n");
441 /* Calculate correlation coefficient between two numeric vectors */
443 correlation(void *buf1
, void *buf2
, uint32 n_elem
, TIFFDataType dtype
)
445 double X
, Y
, M1
= 0.0, M2
= 0.0, D1
= 0.0, D2
= 0.0, K
= 0.0;
451 for (i
= 0; i
< n_elem
; i
++) {
452 X
= ((unsigned char *)buf1
)[i
];
453 Y
= ((unsigned char *)buf2
)[i
];
455 D1
+= X
* X
, D2
+= Y
* Y
;
460 for (i
= 0; i
< n_elem
; i
++) {
461 X
= ((signed char *)buf1
)[i
];
462 Y
= ((signed char *)buf2
)[i
];
464 D1
+= X
* X
, D2
+= Y
* Y
;
469 for (i
= 0; i
< n_elem
; i
++) {
470 X
= ((uint16
*)buf1
)[i
];
471 Y
= ((uint16
*)buf2
)[i
];
473 D1
+= X
* X
, D2
+= Y
* Y
;
478 for (i
= 0; i
< n_elem
; i
++) {
479 X
= ((int16
*)buf1
)[i
];
480 Y
= ((int16
*)buf2
)[i
];
482 D1
+= X
* X
, D2
+= Y
* Y
;
487 for (i
= 0; i
< n_elem
; i
++) {
488 X
= ((uint32
*)buf1
)[i
];
489 Y
= ((uint32
*)buf2
)[i
];
491 D1
+= X
* X
, D2
+= Y
* Y
;
496 for (i
= 0; i
< n_elem
; i
++) {
497 X
= ((int32
*)buf1
)[i
];
498 Y
= ((int32
*)buf2
)[i
];
500 D1
+= X
* X
, D2
+= Y
* Y
;
505 for (i
= 0; i
< n_elem
; i
++) {
506 X
= ((float *)buf1
)[i
];
507 Y
= ((float *)buf2
)[i
];
509 D1
+= X
* X
, D2
+= Y
* Y
;
514 for (i
= 0; i
< n_elem
; i
++) {
515 X
= ((double *)buf1
)[i
];
516 Y
= ((double *)buf2
)[i
];
518 D1
+= X
* X
, D2
+= Y
* Y
;
526 D1
-= M1
* M1
* n_elem
;
527 D2
-= M2
* M2
* n_elem
;
528 K
= (K
- M1
* M2
* n_elem
) / sqrt(D1
* D2
);
534 processCompressOptions(char* opt
)
536 if (strcmp(opt
, "none") == 0)
537 compression
= COMPRESSION_NONE
;
538 else if (strcmp(opt
, "packbits") == 0)
539 compression
= COMPRESSION_PACKBITS
;
540 else if (strncmp(opt
, "jpeg", 4) == 0) {
541 char* cp
= strchr(opt
, ':');
543 compression
= COMPRESSION_JPEG
;
546 if (isdigit((int)cp
[1]))
547 quality
= atoi(cp
+1);
548 else if (cp
[1] == 'r' )
549 jpegcolormode
= JPEGCOLORMODE_RAW
;
553 cp
= strchr(cp
+1,':');
555 } else if (strncmp(opt
, "lzw", 3) == 0) {
556 char* cp
= strchr(opt
, ':');
558 predictor
= atoi(cp
+1);
559 compression
= COMPRESSION_LZW
;
560 } else if (strncmp(opt
, "zip", 3) == 0) {
561 char* cp
= strchr(opt
, ':');
563 predictor
= atoi(cp
+1);
564 compression
= COMPRESSION_DEFLATE
;
570 static char* stuff
[] = {
571 "raw2tiff --- tool for converting raw byte sequences in TIFF images",
572 "usage: raw2tiff [options] input.raw output.tif",
573 "where options are:",
574 " -L input data has LSB2MSB bit order (default)",
575 " -M input data has MSB2LSB bit order",
576 " -r # make each strip have no more than # rows",
577 " -H # size of input image file header in bytes (0 by default)",
578 " -w # width of input image in pixels",
579 " -l # length of input image in lines",
580 " -b # number of bands in input image (1 by default)",
582 " -d data_type type of samples in input image",
583 "where data_type may be:",
584 " byte 8-bit unsigned integer (default)",
585 " short 16-bit unsigned integer",
586 " long 32-bit unsigned integer",
587 " sbyte 8-bit signed integer",
588 " sshort 16-bit signed integer",
589 " slong 32-bit signed integer",
590 " float 32-bit IEEE floating point",
591 " double 64-bit IEEE floating point",
593 " -p photo photometric interpretation (color space) of the input image",
594 "where photo may be:",
595 " miniswhite white color represented with 0 value",
596 " minisblack black color represented with 0 value (default)",
597 " rgb image has RGB color model",
598 " cmyk image has CMYK (separated) color model",
599 " ycbcr image has YCbCr color model",
600 " cielab image has CIE L*a*b color model",
601 " icclab image has ICC L*a*b color model",
602 " itulab image has ITU L*a*b color model",
604 " -s swap bytes fetched from input file",
606 " -i config type of samples interleaving in input image",
607 "where config may be:",
608 " pixel pixel interleaved data (default)",
609 " band band interleaved data",
611 " -c lzw[:opts] compress output with Lempel-Ziv & Welch encoding",
612 " -c zip[:opts] compress output with deflate encoding",
613 " -c jpeg[:opts] compress output with JPEG encoding",
614 " -c packbits compress output with packbits encoding",
615 " -c none use no compression algorithm on output",
618 " # set compression quality level (0-100, default 75)",
619 " r output color image as RGB rather than YCbCr",
620 "For example, -c jpeg:r:50 to get JPEG-encoded RGB data with 50% comp. quality",
622 "LZW and deflate options:",
623 " # set predictor value",
624 "For example, -c lzw:2 to get LZW-encoded data with horizontal differencing",
625 " -o out.tif write output to out.tif",
626 " -h this help message",
637 fprintf(stderr
, "%s\n\n", TIFFGetVersion());
638 for (i
= 0; stuff
[i
] != NULL
; i
++)
639 fprintf(stderr
, "%s\n", stuff
[i
]);
643 /* vim: set ts=8 sts=8 sw=8 noet: */