4 * Copyright (c) 1988-1997 Sam Leffler
5 * Copyright (c) 1991-1997 Silicon Graphics, Inc.
6 * Copyright (c) 2003, Andrey Kiselev <dron@ak4719.spb.edu>
8 * Permission to use, copy, modify, distribute, and sell this software and
9 * its documentation for any purpose is hereby granted without fee, provided
10 * that (i) the above copyright notices and this permission notice appear in
11 * all copies of the software and related documentation, and (ii) the names of
12 * Sam Leffler and Silicon Graphics may not be used in any advertising or
13 * publicity relating to the software without the specific, prior written
14 * permission of Sam Leffler and Silicon Graphics.
16 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
18 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
20 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
21 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
22 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
23 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
24 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
28 #include "tif_config.h"
34 #if HAVE_APPLE_OPENGL_FRAMEWORK
35 # include <OpenGL/gl.h>
36 # 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
], 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 _TIFFfree(raster
), raster
= NULL
;
230 raster
= (uint32
*) _TIFFmalloc(img
.width
* img
.height
* sizeof (uint32
));
231 if (raster
== NULL
) {
233 TIFFError(filelist
[fileindex
], "No space for raster buffer");
239 TIFFRGBAImageGet(&img
, raster
, img
.width
, img
.height
);
241 TIFFSwabArrayOfLong(raster
,img
.width
*img
.height
);
255 tif
= TIFFOpen(filelist
[fileindex
], "r");
264 if (fileindex
< filenum
- 1)
270 tif
= TIFFOpen(filelist
[fileindex
], "r");
279 glutReshapeWindow(width
, height
);
285 glDrawPixels(img
.width
, img
.height
, GL_RGBA
, GL_UNSIGNED_BYTE
, (const GLvoid
*) raster
);
289 raster_reshape(int win_w
, int win_h
)
291 GLfloat xratio
= (GLfloat
)win_w
/img
.width
;
292 GLfloat yratio
= (GLfloat
)win_h
/img
.height
;
293 int ratio
= (int)(((xratio
> yratio
)?xratio
:yratio
) * 100);
295 glPixelZoom(xratio
, yratio
);
296 glViewport(0, 0, win_w
, win_h
);
297 snprintf(title
, 1024, "%s [%u] %d%%", filelist
[fileindex
],
298 (unsigned int) TIFFCurrentDirectory(tif
), ratio
);
299 glutSetWindowTitle(title
);
303 raster_keys(unsigned char key
, int x
, int y
)
306 case 'b': /* photometric MinIsBlack */
307 photo
= PHOTOMETRIC_MINISBLACK
;
310 case 'l': /* lsb-to-msb FillOrder */
311 order
= FILLORDER_LSB2MSB
;
314 case 'm': /* msb-to-lsb FillOrder */
315 order
= FILLORDER_MSB2LSB
;
318 case 'w': /* photometric MinIsWhite */
319 photo
= PHOTOMETRIC_MINISWHITE
;
322 case 'W': /* toggle warnings */
323 owarning
= TIFFSetWarningHandler(owarning
);
326 case 'E': /* toggle errors */
327 oerror
= TIFFSetErrorHandler(oerror
);
330 case 'z': /* reset to defaults */
334 if (owarning
== NULL
)
335 owarning
= TIFFSetWarningHandler(NULL
);
337 oerror
= TIFFSetErrorHandler(NULL
);
348 raster_special(int key
, int x
, int y
)
351 case GLUT_KEY_PAGE_UP
: /* previous logical image */
352 if (TIFFCurrentDirectory(tif
) > 0) {
353 if (TIFFSetDirectory(tif
,
354 TIFFCurrentDirectory(tif
)-1)) {
359 TIFFRGBAImageEnd(&img
);
365 case GLUT_KEY_PAGE_DOWN
: /* next logical image */
366 if (!TIFFLastDirectory(tif
)) {
367 if (TIFFReadDirectory(tif
)) {
372 TIFFRGBAImageEnd(&img
);
378 case GLUT_KEY_HOME
: /* 1st image in current file */
379 if (TIFFSetDirectory(tif
, 0)) {
380 TIFFRGBAImageEnd(&img
);
385 case GLUT_KEY_END
: /* last image in current file */
386 TIFFRGBAImageEnd(&img
);
387 while (!TIFFLastDirectory(tif
))
388 TIFFReadDirectory(tif
);
399 "usage: tiffgt [options] file.tif",
400 "where options are:",
401 " -c use colormap visual",
402 " -d dirnum set initial directory (default is 0)",
403 " -e enable display of TIFF error messages",
404 " -l force lsb-to-msb FillOrder",
405 " -m force msb-to-lsb FillOrder",
406 " -o offset set initial directory offset",
407 " -p photo override photometric interpretation",
408 " -r use fullcolor visual",
409 " -s stop decoding on first error (default is ignore errors)",
410 " -v enable verbose mode",
411 " -w enable display of TIFF warning messages",
422 fprintf(stderr
, "%s\n\n", TIFFGetVersion());
423 for (i
= 0; stuff
[i
] != NULL
; i
++)
424 fprintf(stderr
, "%s\n", stuff
[i
]);
429 photoArg(const char* arg
)
431 if (strcmp(arg
, "miniswhite") == 0)
432 return (PHOTOMETRIC_MINISWHITE
);
433 else if (strcmp(arg
, "minisblack") == 0)
434 return (PHOTOMETRIC_MINISBLACK
);
435 else if (strcmp(arg
, "rgb") == 0)
436 return (PHOTOMETRIC_RGB
);
437 else if (strcmp(arg
, "palette") == 0)
438 return (PHOTOMETRIC_PALETTE
);
439 else if (strcmp(arg
, "mask") == 0)
440 return (PHOTOMETRIC_MASK
);
441 else if (strcmp(arg
, "separated") == 0)
442 return (PHOTOMETRIC_SEPARATED
);
443 else if (strcmp(arg
, "ycbcr") == 0)
444 return (PHOTOMETRIC_YCBCR
);
445 else if (strcmp(arg
, "cielab") == 0)
446 return (PHOTOMETRIC_CIELAB
);
447 else if (strcmp(arg
, "logl") == 0)
448 return (PHOTOMETRIC_LOGL
);
449 else if (strcmp(arg
, "logluv") == 0)
450 return (PHOTOMETRIC_LOGLUV
);
452 return ((uint16
) -1);
455 /* vim: set ts=8 sts=8 sw=8 noet: */