3 * Copyright (c) 1988-1997 Sam Leffler
4 * Copyright (c) 1991-1997 Silicon Graphics, Inc.
5 * Copyright (c) 2003, Andrey Kiselev <dron@ak4719.spb.edu>
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.
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.
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
27 #include "tif_config.h"
33 #if HAVE_APPLE_OPENGL_FRAMEWORK
34 # include <OpenGL/gl.h>
35 # include <GLUT/glut.h>
45 extern int getopt(int, char**, char*);
48 static uint32 width
= 0, height
= 0; /* window width & height */
49 static uint32
* raster
= NULL
; /* displayable image */
50 static TIFFRGBAImage img
;
51 static int order0
= 0, order
;
52 static uint16 photo0
= (uint16
) -1, photo
;
53 static int stoponerr
= 0; /* stop on read error */
54 static int verbose
= 0;
55 #define TITLE_LENGTH 1024
56 static char title
[TITLE_LENGTH
]; /* window title line */
57 static uint32 xmax
, ymax
;
58 static char** filelist
= NULL
;
61 static TIFFErrorHandler oerror
;
62 static TIFFErrorHandler owarning
;
64 static void cleanup_and_exit(void);
65 static int initImage(void);
66 static int prevImage(void);
67 static int nextImage(void);
68 static void setWindowSize(void);
69 static void usage(void);
70 static uint16
photoArg(const char*);
71 static void raster_draw(void);
72 static void raster_reshape(int, int);
73 static void raster_keys(unsigned char, int, int);
74 static void raster_special(int, int, int);
78 static TIFF
* tif
= NULL
;
81 main(int argc
, char* argv
[])
87 oerror
= TIFFSetErrorHandler(NULL
);
88 owarning
= TIFFSetWarningHandler(NULL
);
89 while ((c
= getopt(argc
, argv
, "d:o:p:eflmsvw?")) != -1)
92 dirnum
= atoi(optarg
);
95 oerror
= TIFFSetErrorHandler(oerror
);
98 order0
= FILLORDER_LSB2MSB
;
101 order0
= FILLORDER_MSB2LSB
;
104 diroff
= strtoul(optarg
, NULL
, 0);
107 photo0
= photoArg(optarg
);
113 owarning
= TIFFSetWarningHandler(owarning
);
122 filenum
= argc
- optind
;
126 glutInit(&argc
, argv
);
127 glutInitDisplayMode(GLUT_SINGLE
| GLUT_RGB
);
130 * Get the screen size
132 xmax
= glutGet(GLUT_SCREEN_WIDTH
);
133 ymax
= glutGet(GLUT_SCREEN_HEIGHT
);
136 * Use 90% of the screen size
138 xmax
= xmax
- xmax
/ 10.0;
139 ymax
= ymax
- ymax
/ 10.0;
141 filelist
= (char **) _TIFFmalloc(filenum
* sizeof(char*));
143 TIFFError(argv
[0], "Can not allocate space for the file list.");
146 _TIFFmemcpy(filelist
, argv
+ optind
, filenum
* sizeof(char*));
148 if (nextImage() < 0) {
153 * Set initial directory if user-specified
154 * file was opened successfully.
156 if (dirnum
!= -1 && !TIFFSetDirectory(tif
, dirnum
))
157 TIFFError(argv
[0], "Error, seeking to directory %d", dirnum
);
158 if (diroff
!= 0 && !TIFFSetSubDirectory(tif
, diroff
))
159 TIFFError(argv
[0], "Error, setting subdirectory at %#x", diroff
);
162 if (initImage() < 0){
167 * Create a new window or reconfigure an existing
168 * one to suit the image to be displayed.
170 glutInitWindowSize(width
, height
);
171 snprintf(title
, TITLE_LENGTH
- 1, "%s [%u]", filelist
[fileindex
],
172 (unsigned int) TIFFCurrentDirectory(tif
));
173 glutCreateWindow(title
);
174 glutDisplayFunc(raster_draw
);
175 glutReshapeFunc(raster_reshape
);
176 glutKeyboardFunc(raster_keys
);
177 glutSpecialFunc(raster_special
);
185 cleanup_and_exit(void)
187 TIFFRGBAImageEnd(&img
);
188 if (filelist
!= NULL
)
203 TIFFSetField(tif
, TIFFTAG_FILLORDER
, order
);
204 if (photo
!= (uint16
) -1)
205 TIFFSetField(tif
, TIFFTAG_PHOTOMETRIC
, photo
);
206 if (!TIFFRGBAImageBegin(&img
, tif
, stoponerr
, title
)) {
207 TIFFError(filelist
[fileindex
], "%s", title
);
214 * Setup the image raster as required.
219 w
= (int)(w
* ((float)ymax
/ h
));
223 h
= (int)(h
* ((float)xmax
/ w
));
227 if (w
!= width
|| h
!= height
) {
229 _TIFFMultiply32(tif
, img
.width
, img
.height
, "allocating raster buffer");
231 _TIFFfree(raster
), raster
= NULL
;
232 raster
= (uint32
*) _TIFFCheckMalloc(tif
, rastersize
, sizeof (uint32
),
233 "allocating raster buffer");
234 if (raster
== NULL
) {
236 TIFFError(filelist
[fileindex
], "No space for raster buffer");
242 TIFFRGBAImageGet(&img
, raster
, img
.width
, img
.height
);
244 TIFFSwabArrayOfLong(raster
,img
.width
*img
.height
);
258 tif
= TIFFOpen(filelist
[fileindex
], "r");
267 if (fileindex
< filenum
- 1)
273 tif
= TIFFOpen(filelist
[fileindex
], "r");
282 glutReshapeWindow(width
, height
);
288 glDrawPixels(img
.width
, img
.height
, GL_RGBA
, GL_UNSIGNED_BYTE
, (const GLvoid
*) raster
);
292 raster_reshape(int win_w
, int win_h
)
294 GLfloat xratio
= (GLfloat
)win_w
/img
.width
;
295 GLfloat yratio
= (GLfloat
)win_h
/img
.height
;
296 int ratio
= (int)(((xratio
> yratio
)?xratio
:yratio
) * 100);
298 glPixelZoom(xratio
, yratio
);
299 glViewport(0, 0, win_w
, win_h
);
300 snprintf(title
, 1024, "%s [%u] %d%%", filelist
[fileindex
],
301 (unsigned int) TIFFCurrentDirectory(tif
), ratio
);
302 glutSetWindowTitle(title
);
306 raster_keys(unsigned char key
, int x
, int y
)
309 case 'b': /* photometric MinIsBlack */
310 photo
= PHOTOMETRIC_MINISBLACK
;
313 case 'l': /* lsb-to-msb FillOrder */
314 order
= FILLORDER_LSB2MSB
;
317 case 'm': /* msb-to-lsb FillOrder */
318 order
= FILLORDER_MSB2LSB
;
321 case 'w': /* photometric MinIsWhite */
322 photo
= PHOTOMETRIC_MINISWHITE
;
325 case 'W': /* toggle warnings */
326 owarning
= TIFFSetWarningHandler(owarning
);
329 case 'E': /* toggle errors */
330 oerror
= TIFFSetErrorHandler(oerror
);
333 case 'z': /* reset to defaults */
337 if (owarning
== NULL
)
338 owarning
= TIFFSetWarningHandler(NULL
);
340 oerror
= TIFFSetErrorHandler(NULL
);
351 raster_special(int key
, int x
, int y
)
354 case GLUT_KEY_PAGE_UP
: /* previous logical image */
355 if (TIFFCurrentDirectory(tif
) > 0) {
356 if (TIFFSetDirectory(tif
,
357 TIFFCurrentDirectory(tif
)-1)) {
362 TIFFRGBAImageEnd(&img
);
368 case GLUT_KEY_PAGE_DOWN
: /* next logical image */
369 if (!TIFFLastDirectory(tif
)) {
370 if (TIFFReadDirectory(tif
)) {
375 TIFFRGBAImageEnd(&img
);
381 case GLUT_KEY_HOME
: /* 1st image in current file */
382 if (TIFFSetDirectory(tif
, 0)) {
383 TIFFRGBAImageEnd(&img
);
388 case GLUT_KEY_END
: /* last image in current file */
389 TIFFRGBAImageEnd(&img
);
390 while (!TIFFLastDirectory(tif
))
391 TIFFReadDirectory(tif
);
402 "usage: tiffgt [options] file.tif",
403 "where options are:",
404 " -c use colormap visual",
405 " -d dirnum set initial directory (default is 0)",
406 " -e enable display of TIFF error messages",
407 " -l force lsb-to-msb FillOrder",
408 " -m force msb-to-lsb FillOrder",
409 " -o offset set initial directory offset",
410 " -p photo override photometric interpretation",
411 " -r use fullcolor visual",
412 " -s stop decoding on first error (default is ignore errors)",
413 " -v enable verbose mode",
414 " -w enable display of TIFF warning messages",
425 fprintf(stderr
, "%s\n\n", TIFFGetVersion());
426 for (i
= 0; stuff
[i
] != NULL
; i
++)
427 fprintf(stderr
, "%s\n", stuff
[i
]);
432 photoArg(const char* arg
)
434 if (strcmp(arg
, "miniswhite") == 0)
435 return (PHOTOMETRIC_MINISWHITE
);
436 else if (strcmp(arg
, "minisblack") == 0)
437 return (PHOTOMETRIC_MINISBLACK
);
438 else if (strcmp(arg
, "rgb") == 0)
439 return (PHOTOMETRIC_RGB
);
440 else if (strcmp(arg
, "palette") == 0)
441 return (PHOTOMETRIC_PALETTE
);
442 else if (strcmp(arg
, "mask") == 0)
443 return (PHOTOMETRIC_MASK
);
444 else if (strcmp(arg
, "separated") == 0)
445 return (PHOTOMETRIC_SEPARATED
);
446 else if (strcmp(arg
, "ycbcr") == 0)
447 return (PHOTOMETRIC_YCBCR
);
448 else if (strcmp(arg
, "cielab") == 0)
449 return (PHOTOMETRIC_CIELAB
);
450 else if (strcmp(arg
, "logl") == 0)
451 return (PHOTOMETRIC_LOGL
);
452 else if (strcmp(arg
, "logluv") == 0)
453 return (PHOTOMETRIC_LOGLUV
);
455 return ((uint16
) -1);
458 /* vim: set ts=8 sts=8 sw=8 noet: */