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>
46 extern int getopt(int, char**, char*);
49 static uint32 width
= 0, height
= 0; /* window width & height */
50 static uint32
* raster
= NULL
; /* displayable image */
51 static TIFFRGBAImage img
;
52 static int order0
= 0, order
;
53 static uint16 photo0
= (uint16
) -1, photo
;
54 static int stoponerr
= 0; /* stop on read error */
55 static int verbose
= 0;
56 #define TITLE_LENGTH 1024
57 static char title
[TITLE_LENGTH
]; /* window title line */
58 static uint32 xmax
, ymax
;
59 static char** filelist
= NULL
;
62 static TIFFErrorHandler oerror
;
63 static TIFFErrorHandler owarning
;
65 static void cleanup_and_exit(void);
66 static int initImage(void);
67 static int prevImage(void);
68 static int nextImage(void);
69 static void setWindowSize(void);
70 static void usage(void);
71 static uint16
photoArg(const char*);
72 static void raster_draw(void);
73 static void raster_reshape(int, int);
74 static void raster_keys(unsigned char, int, int);
75 static void raster_special(int, int, int);
79 static TIFF
* tif
= NULL
;
82 main(int argc
, char* argv
[])
88 oerror
= TIFFSetErrorHandler(NULL
);
89 owarning
= TIFFSetWarningHandler(NULL
);
90 while ((c
= getopt(argc
, argv
, "d:o:p:eflmsvw?")) != -1)
93 dirnum
= atoi(optarg
);
96 oerror
= TIFFSetErrorHandler(oerror
);
99 order0
= FILLORDER_LSB2MSB
;
102 order0
= FILLORDER_MSB2LSB
;
105 diroff
= strtoul(optarg
, NULL
, 0);
108 photo0
= photoArg(optarg
);
114 owarning
= TIFFSetWarningHandler(owarning
);
123 filenum
= argc
- optind
;
127 glutInit(&argc
, argv
);
128 glutInitDisplayMode(GLUT_SINGLE
| GLUT_RGB
);
131 * Get the screen size
133 xmax
= glutGet(GLUT_SCREEN_WIDTH
);
134 ymax
= glutGet(GLUT_SCREEN_HEIGHT
);
137 * Use 90% of the screen size
139 xmax
= xmax
- xmax
/ 10.0;
140 ymax
= ymax
- ymax
/ 10.0;
142 filelist
= (char **) _TIFFmalloc(filenum
* sizeof(char*));
144 TIFFError(argv
[0], "Can not allocate space for the file list.");
147 _TIFFmemcpy(filelist
, argv
+ optind
, filenum
* sizeof(char*));
149 if (nextImage() < 0) {
154 * Set initial directory if user-specified
155 * file was opened successfully.
157 if (dirnum
!= -1 && !TIFFSetDirectory(tif
, dirnum
))
158 TIFFError(argv
[0], "Error, seeking to directory %d", dirnum
);
159 if (diroff
!= 0 && !TIFFSetSubDirectory(tif
, diroff
))
160 TIFFError(argv
[0], "Error, setting subdirectory at %#x", diroff
);
163 if (initImage() < 0){
168 * Create a new window or reconfigure an existing
169 * one to suit the image to be displayed.
171 glutInitWindowSize(width
, height
);
172 snprintf(title
, TITLE_LENGTH
- 1, "%s [%u]", filelist
[fileindex
],
173 (unsigned int) TIFFCurrentDirectory(tif
));
174 glutCreateWindow(title
);
175 glutDisplayFunc(raster_draw
);
176 glutReshapeFunc(raster_reshape
);
177 glutKeyboardFunc(raster_keys
);
178 glutSpecialFunc(raster_special
);
186 cleanup_and_exit(void)
188 TIFFRGBAImageEnd(&img
);
189 if (filelist
!= NULL
)
204 TIFFSetField(tif
, TIFFTAG_FILLORDER
, order
);
205 if (photo
!= (uint16
) -1)
206 TIFFSetField(tif
, TIFFTAG_PHOTOMETRIC
, photo
);
207 if (!TIFFRGBAImageBegin(&img
, tif
, stoponerr
, title
)) {
208 TIFFError(filelist
[fileindex
], "%s", title
);
215 * Setup the image raster as required.
220 w
= (int)(w
* ((float)ymax
/ h
));
224 h
= (int)(h
* ((float)xmax
/ w
));
228 if (w
!= width
|| h
!= height
) {
230 _TIFFMultiply32(tif
, img
.width
, img
.height
, "allocating raster buffer");
232 _TIFFfree(raster
), raster
= NULL
;
233 raster
= (uint32
*) _TIFFCheckMalloc(tif
, rastersize
, sizeof (uint32
),
234 "allocating raster buffer");
235 if (raster
== NULL
) {
237 TIFFError(filelist
[fileindex
], "No space for raster buffer");
243 TIFFRGBAImageGet(&img
, raster
, img
.width
, img
.height
);
245 TIFFSwabArrayOfLong(raster
,img
.width
*img
.height
);
259 tif
= TIFFOpen(filelist
[fileindex
], "r");
268 if (fileindex
< filenum
- 1)
274 tif
= TIFFOpen(filelist
[fileindex
], "r");
283 glutReshapeWindow(width
, height
);
289 glDrawPixels(img
.width
, img
.height
, GL_RGBA
, GL_UNSIGNED_BYTE
, (const GLvoid
*) raster
);
293 raster_reshape(int win_w
, int win_h
)
295 GLfloat xratio
= (GLfloat
)win_w
/img
.width
;
296 GLfloat yratio
= (GLfloat
)win_h
/img
.height
;
297 int ratio
= (int)(((xratio
> yratio
)?xratio
:yratio
) * 100);
299 glPixelZoom(xratio
, yratio
);
300 glViewport(0, 0, win_w
, win_h
);
301 snprintf(title
, 1024, "%s [%u] %d%%", filelist
[fileindex
],
302 (unsigned int) TIFFCurrentDirectory(tif
), ratio
);
303 glutSetWindowTitle(title
);
307 raster_keys(unsigned char key
, int x
, int y
)
310 case 'b': /* photometric MinIsBlack */
311 photo
= PHOTOMETRIC_MINISBLACK
;
314 case 'l': /* lsb-to-msb FillOrder */
315 order
= FILLORDER_LSB2MSB
;
318 case 'm': /* msb-to-lsb FillOrder */
319 order
= FILLORDER_MSB2LSB
;
322 case 'w': /* photometric MinIsWhite */
323 photo
= PHOTOMETRIC_MINISWHITE
;
326 case 'W': /* toggle warnings */
327 owarning
= TIFFSetWarningHandler(owarning
);
330 case 'E': /* toggle errors */
331 oerror
= TIFFSetErrorHandler(oerror
);
334 case 'z': /* reset to defaults */
338 if (owarning
== NULL
)
339 owarning
= TIFFSetWarningHandler(NULL
);
341 oerror
= TIFFSetErrorHandler(NULL
);
352 raster_special(int key
, int x
, int y
)
355 case GLUT_KEY_PAGE_UP
: /* previous logical image */
356 if (TIFFCurrentDirectory(tif
) > 0) {
357 if (TIFFSetDirectory(tif
,
358 TIFFCurrentDirectory(tif
)-1)) {
363 TIFFRGBAImageEnd(&img
);
369 case GLUT_KEY_PAGE_DOWN
: /* next logical image */
370 if (!TIFFLastDirectory(tif
)) {
371 if (TIFFReadDirectory(tif
)) {
376 TIFFRGBAImageEnd(&img
);
382 case GLUT_KEY_HOME
: /* 1st image in current file */
383 if (TIFFSetDirectory(tif
, 0)) {
384 TIFFRGBAImageEnd(&img
);
389 case GLUT_KEY_END
: /* last image in current file */
390 TIFFRGBAImageEnd(&img
);
391 while (!TIFFLastDirectory(tif
))
392 TIFFReadDirectory(tif
);
403 "usage: tiffgt [options] file.tif",
404 "where options are:",
405 " -c use colormap visual",
406 " -d dirnum set initial directory (default is 0)",
407 " -e enable display of TIFF error messages",
408 " -l force lsb-to-msb FillOrder",
409 " -m force msb-to-lsb FillOrder",
410 " -o offset set initial directory offset",
411 " -p photo override photometric interpretation",
412 " -r use fullcolor visual",
413 " -s stop decoding on first error (default is ignore errors)",
414 " -v enable verbose mode",
415 " -w enable display of TIFF warning messages",
426 fprintf(stderr
, "%s\n\n", TIFFGetVersion());
427 for (i
= 0; stuff
[i
] != NULL
; i
++)
428 fprintf(stderr
, "%s\n", stuff
[i
]);
433 photoArg(const char* arg
)
435 if (strcmp(arg
, "miniswhite") == 0)
436 return (PHOTOMETRIC_MINISWHITE
);
437 else if (strcmp(arg
, "minisblack") == 0)
438 return (PHOTOMETRIC_MINISBLACK
);
439 else if (strcmp(arg
, "rgb") == 0)
440 return (PHOTOMETRIC_RGB
);
441 else if (strcmp(arg
, "palette") == 0)
442 return (PHOTOMETRIC_PALETTE
);
443 else if (strcmp(arg
, "mask") == 0)
444 return (PHOTOMETRIC_MASK
);
445 else if (strcmp(arg
, "separated") == 0)
446 return (PHOTOMETRIC_SEPARATED
);
447 else if (strcmp(arg
, "ycbcr") == 0)
448 return (PHOTOMETRIC_YCBCR
);
449 else if (strcmp(arg
, "cielab") == 0)
450 return (PHOTOMETRIC_CIELAB
);
451 else if (strcmp(arg
, "logl") == 0)
452 return (PHOTOMETRIC_LOGL
);
453 else if (strcmp(arg
, "logluv") == 0)
454 return (PHOTOMETRIC_LOGLUV
);
456 return ((uint16
) -1);
459 /* vim: set ts=8 sts=8 sw=8 noet: */