1 /* $Id: tiffgt.c,v 1.10 2010-07-01 15:56:56 dron Exp $ */
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: */