kusano 7d535a
/* $Id: tiffgt.c,v 1.10 2010-07-01 15:56:56 dron Exp $ */
kusano 7d535a
kusano 7d535a
/*
kusano 7d535a
 * Copyright (c) 1988-1997 Sam Leffler
kusano 7d535a
 * Copyright (c) 1991-1997 Silicon Graphics, Inc.
kusano 7d535a
 * Copyright (c) 2003, Andrey Kiselev <dron@ak4719.spb.edu></dron@ak4719.spb.edu>
kusano 7d535a
 *
kusano 7d535a
 * Permission to use, copy, modify, distribute, and sell this software and 
kusano 7d535a
 * its documentation for any purpose is hereby granted without fee, provided
kusano 7d535a
 * that (i) the above copyright notices and this permission notice appear in
kusano 7d535a
 * all copies of the software and related documentation, and (ii) the names of
kusano 7d535a
 * Sam Leffler and Silicon Graphics may not be used in any advertising or
kusano 7d535a
 * publicity relating to the software without the specific, prior written
kusano 7d535a
 * permission of Sam Leffler and Silicon Graphics.
kusano 7d535a
 * 
kusano 7d535a
 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
kusano 7d535a
 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
kusano 7d535a
 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
kusano 7d535a
 * 
kusano 7d535a
 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
kusano 7d535a
 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
kusano 7d535a
 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
kusano 7d535a
 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
kusano 7d535a
 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
kusano 7d535a
 * OF THIS SOFTWARE.
kusano 7d535a
 */
kusano 7d535a
kusano 7d535a
#include "tif_config.h"
kusano 7d535a
#include <stdio.h></stdio.h>
kusano 7d535a
#include <stdlib.h></stdlib.h>
kusano 7d535a
#include <string.h></string.h>
kusano 7d535a
#include <unistd.h></unistd.h>
kusano 7d535a
kusano 7d535a
#if HAVE_APPLE_OPENGL_FRAMEWORK
kusano 7d535a
# include <opengl gl.h=""></opengl>
kusano 7d535a
# include <glut glut.h=""></glut>
kusano 7d535a
#else
kusano 7d535a
# include <gl gl.h=""></gl>
kusano 7d535a
# include <gl glut.h=""></gl>
kusano 7d535a
#endif
kusano 7d535a
kusano 7d535a
#include "tiffio.h"
kusano 7d535a
#include "tiffiop.h"
kusano 7d535a
kusano 7d535a
#ifndef HAVE_GETOPT
kusano 7d535a
extern int getopt(int, char**, char*);
kusano 7d535a
#endif
kusano 7d535a
kusano 7d535a
static  uint32  width = 0, height = 0;          /* window width & height */
kusano 7d535a
static  uint32* raster = NULL;                  /* displayable image */
kusano 7d535a
static TIFFRGBAImage img;
kusano 7d535a
static int      order0 = 0, order;
kusano 7d535a
static uint16   photo0 = (uint16) -1, photo;
kusano 7d535a
static int      stoponerr = 0;                  /* stop on read error */
kusano 7d535a
static int      verbose = 0;
kusano 7d535a
#define TITLE_LENGTH    1024
kusano 7d535a
static char     title[TITLE_LENGTH];            /* window title line */
kusano 7d535a
static uint32   xmax, ymax;
kusano 7d535a
static char**   filelist = NULL;
kusano 7d535a
static int      fileindex;
kusano 7d535a
static int      filenum;
kusano 7d535a
static TIFFErrorHandler oerror;
kusano 7d535a
static TIFFErrorHandler owarning;
kusano 7d535a
kusano 7d535a
static void	cleanup_and_exit(void);
kusano 7d535a
static int	initImage(void);
kusano 7d535a
static int	prevImage(void);
kusano 7d535a
static int	nextImage(void);
kusano 7d535a
static void	setWindowSize(void);
kusano 7d535a
static void	usage(void);
kusano 7d535a
static uint16	photoArg(const char*);
kusano 7d535a
static void	raster_draw(void);
kusano 7d535a
static void	raster_reshape(int, int);
kusano 7d535a
static void	raster_keys(unsigned char, int, int);
kusano 7d535a
static void	raster_special(int, int, int);
kusano 7d535a
kusano 7d535a
extern  char* optarg;
kusano 7d535a
extern  int optind;
kusano 7d535a
static TIFF* tif = NULL;
kusano 7d535a
kusano 7d535a
int
kusano 7d535a
main(int argc, char* argv[])
kusano 7d535a
{
kusano 7d535a
        int c;
kusano 7d535a
        int dirnum = -1;
kusano 7d535a
        uint32 diroff = 0;
kusano 7d535a
kusano 7d535a
        oerror = TIFFSetErrorHandler(NULL);
kusano 7d535a
        owarning = TIFFSetWarningHandler(NULL);
kusano 7d535a
        while ((c = getopt(argc, argv, "d:o:p:eflmsvw?")) != -1)
kusano 7d535a
            switch (c) {
kusano 7d535a
            case 'd':
kusano 7d535a
                dirnum = atoi(optarg);
kusano 7d535a
                break;
kusano 7d535a
            case 'e':
kusano 7d535a
                oerror = TIFFSetErrorHandler(oerror);
kusano 7d535a
                break;
kusano 7d535a
            case 'l':
kusano 7d535a
                order0 = FILLORDER_LSB2MSB;
kusano 7d535a
                break;
kusano 7d535a
            case 'm':
kusano 7d535a
                order0 = FILLORDER_MSB2LSB;
kusano 7d535a
                break;
kusano 7d535a
            case 'o':
kusano 7d535a
                diroff = strtoul(optarg, NULL, 0);
kusano 7d535a
                break;
kusano 7d535a
            case 'p':
kusano 7d535a
                photo0 = photoArg(optarg);
kusano 7d535a
                break;
kusano 7d535a
            case 's':
kusano 7d535a
                stoponerr = 1;
kusano 7d535a
                break;
kusano 7d535a
            case 'w':
kusano 7d535a
                owarning = TIFFSetWarningHandler(owarning);
kusano 7d535a
                break;
kusano 7d535a
            case 'v':
kusano 7d535a
                verbose = 1;
kusano 7d535a
                break;
kusano 7d535a
            case '?':
kusano 7d535a
                usage();
kusano 7d535a
                /*NOTREACHED*/
kusano 7d535a
            }
kusano 7d535a
        filenum = argc - optind;
kusano 7d535a
        if ( filenum < 1)
kusano 7d535a
                usage();
kusano 7d535a
kusano 7d535a
        glutInit(&argc, argv);
kusano 7d535a
        glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
kusano 7d535a
kusano 7d535a
        /*
kusano 7d535a
         * Get the screen size
kusano 7d535a
         */
kusano 7d535a
        xmax = glutGet(GLUT_SCREEN_WIDTH);
kusano 7d535a
        ymax = glutGet(GLUT_SCREEN_HEIGHT);
kusano 7d535a
kusano 7d535a
        /*
kusano 7d535a
         * Use 90% of the screen size
kusano 7d535a
         */
kusano 7d535a
        xmax = xmax - xmax / 10.0;
kusano 7d535a
        ymax = ymax - ymax / 10.0;
kusano 7d535a
kusano 7d535a
        filelist = (char **) _TIFFmalloc(filenum * sizeof(char*));
kusano 7d535a
        if (!filelist) {
kusano 7d535a
                TIFFError(argv[0], "Can not allocate space for the file list.");
kusano 7d535a
                return 1;
kusano 7d535a
        }
kusano 7d535a
        _TIFFmemcpy(filelist, argv + optind, filenum * sizeof(char*));
kusano 7d535a
        fileindex = -1;
kusano 7d535a
        if (nextImage() < 0) {
kusano 7d535a
                _TIFFfree(filelist);
kusano 7d535a
                return 2;
kusano 7d535a
        }
kusano 7d535a
        /*
kusano 7d535a
         * Set initial directory if user-specified
kusano 7d535a
         * file was opened successfully.
kusano 7d535a
         */
kusano 7d535a
        if (dirnum != -1 && !TIFFSetDirectory(tif, dirnum))
kusano 7d535a
            TIFFError(argv[0], "Error, seeking to directory %d", dirnum);
kusano 7d535a
        if (diroff != 0 && !TIFFSetSubDirectory(tif, diroff))
kusano 7d535a
            TIFFError(argv[0], "Error, setting subdirectory at %#x", diroff);
kusano 7d535a
        order = order0;
kusano 7d535a
        photo = photo0;
kusano 7d535a
	if (initImage() < 0){
kusano 7d535a
                _TIFFfree(filelist);
kusano 7d535a
                return 3;
kusano 7d535a
        }
kusano 7d535a
        /*
kusano 7d535a
         * Create a new window or reconfigure an existing
kusano 7d535a
         * one to suit the image to be displayed.
kusano 7d535a
         */
kusano 7d535a
        glutInitWindowSize(width, height);
kusano 7d535a
        snprintf(title, TITLE_LENGTH - 1, "%s [%u]", filelist[fileindex],
kusano 7d535a
                (unsigned int) TIFFCurrentDirectory(tif));
kusano 7d535a
        glutCreateWindow(title);
kusano 7d535a
        glutDisplayFunc(raster_draw);
kusano 7d535a
        glutReshapeFunc(raster_reshape);
kusano 7d535a
        glutKeyboardFunc(raster_keys);
kusano 7d535a
        glutSpecialFunc(raster_special);
kusano 7d535a
        glutMainLoop();
kusano 7d535a
kusano 7d535a
        cleanup_and_exit();
kusano 7d535a
        return 0;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
static void 
kusano 7d535a
cleanup_and_exit(void)
kusano 7d535a
{
kusano 7d535a
        TIFFRGBAImageEnd(&img);
kusano 7d535a
        if (filelist != NULL)
kusano 7d535a
                _TIFFfree(filelist);
kusano 7d535a
        if (raster != NULL)
kusano 7d535a
                _TIFFfree(raster);
kusano 7d535a
        if (tif != NULL)
kusano 7d535a
                TIFFClose(tif);
kusano 7d535a
        exit(0);
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
static int
kusano 7d535a
initImage(void)
kusano 7d535a
{
kusano 7d535a
        uint32 w, h;
kusano 7d535a
kusano 7d535a
        if (order)
kusano 7d535a
                TIFFSetField(tif, TIFFTAG_FILLORDER, order);
kusano 7d535a
        if (photo != (uint16) -1)
kusano 7d535a
                TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, photo);
kusano 7d535a
        if (!TIFFRGBAImageBegin(&img, tif, stoponerr, title)) {
kusano 7d535a
                TIFFError(filelist[fileindex], "%s", title);
kusano 7d535a
                TIFFClose(tif);
kusano 7d535a
                tif = NULL;
kusano 7d535a
                return -1;
kusano 7d535a
        }
kusano 7d535a
kusano 7d535a
        /*
kusano 7d535a
         * Setup the image raster as required.
kusano 7d535a
         */
kusano 7d535a
        h = img.height;
kusano 7d535a
        w = img.width;
kusano 7d535a
        if (h > ymax) {
kusano 7d535a
                w = (int)(w * ((float)ymax / h));
kusano 7d535a
                h = ymax;
kusano 7d535a
        }
kusano 7d535a
        if (w > xmax) {
kusano 7d535a
                h = (int)(h * ((float)xmax / w));
kusano 7d535a
                w = xmax;
kusano 7d535a
        }
kusano 7d535a
kusano 7d535a
	if (w != width || h != height) {
kusano 7d535a
		uint32 rastersize =
kusano 7d535a
			_TIFFMultiply32(tif, img.width, img.height, "allocating raster buffer");
kusano 7d535a
		if (raster != NULL)
kusano 7d535a
			_TIFFfree(raster), raster = NULL;
kusano 7d535a
		raster = (uint32*) _TIFFCheckMalloc(tif, rastersize, sizeof (uint32),
kusano 7d535a
						    "allocating raster buffer");
kusano 7d535a
		if (raster == NULL) {
kusano 7d535a
			width = height = 0;
kusano 7d535a
			TIFFError(filelist[fileindex], "No space for raster buffer");
kusano 7d535a
			cleanup_and_exit();
kusano 7d535a
		}
kusano 7d535a
		width = w;
kusano 7d535a
		height = h;
kusano 7d535a
	}
kusano 7d535a
	TIFFRGBAImageGet(&img, raster, img.width, img.height);
kusano 7d535a
#if HOST_BIGENDIAN
kusano 7d535a
	TIFFSwabArrayOfLong(raster,img.width*img.height);
kusano 7d535a
#endif
kusano 7d535a
	return 0;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
static int
kusano 7d535a
prevImage(void)
kusano 7d535a
{
kusano 7d535a
        if (fileindex > 0)
kusano 7d535a
                fileindex--;
kusano 7d535a
        else if (tif)
kusano 7d535a
                return fileindex;
kusano 7d535a
        if (tif)
kusano 7d535a
                TIFFClose(tif);
kusano 7d535a
        tif = TIFFOpen(filelist[fileindex], "r");
kusano 7d535a
        if (tif == NULL)
kusano 7d535a
                return -1;
kusano 7d535a
        return fileindex;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
static int
kusano 7d535a
nextImage(void)
kusano 7d535a
{
kusano 7d535a
        if (fileindex < filenum - 1)
kusano 7d535a
                fileindex++;
kusano 7d535a
        else if (tif)
kusano 7d535a
                return fileindex;
kusano 7d535a
        if (tif)
kusano 7d535a
                TIFFClose(tif);
kusano 7d535a
        tif = TIFFOpen(filelist[fileindex], "r");
kusano 7d535a
        if (tif == NULL)
kusano 7d535a
                return -1;
kusano 7d535a
        return fileindex;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
static void
kusano 7d535a
setWindowSize(void)
kusano 7d535a
{
kusano 7d535a
        glutReshapeWindow(width, height);
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
static void
kusano 7d535a
raster_draw(void)
kusano 7d535a
{
kusano 7d535a
  glDrawPixels(img.width, img.height, GL_RGBA, GL_UNSIGNED_BYTE, (const GLvoid *) raster);
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
static void
kusano 7d535a
raster_reshape(int win_w, int win_h)
kusano 7d535a
{
kusano 7d535a
        GLfloat xratio = (GLfloat)win_w/img.width;
kusano 7d535a
        GLfloat yratio = (GLfloat)win_h/img.height;
kusano 7d535a
        int     ratio = (int)(((xratio > yratio)?xratio:yratio) * 100);
kusano 7d535a
kusano 7d535a
        glPixelZoom(xratio, yratio);
kusano 7d535a
        glViewport(0, 0, win_w, win_h);
kusano 7d535a
        snprintf(title, 1024, "%s [%u] %d%%", filelist[fileindex],
kusano 7d535a
                (unsigned int) TIFFCurrentDirectory(tif), ratio);
kusano 7d535a
        glutSetWindowTitle(title);
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
static void
kusano 7d535a
raster_keys(unsigned char key, int x, int y)
kusano 7d535a
{
kusano 7d535a
        switch (key) {
kusano 7d535a
                case 'b':                       /* photometric MinIsBlack */
kusano 7d535a
                    photo = PHOTOMETRIC_MINISBLACK;
kusano 7d535a
                    initImage();
kusano 7d535a
                    break;
kusano 7d535a
                case 'l':                       /* lsb-to-msb FillOrder */
kusano 7d535a
                    order = FILLORDER_LSB2MSB;
kusano 7d535a
                    initImage();
kusano 7d535a
                    break;
kusano 7d535a
                case 'm':                       /* msb-to-lsb FillOrder */
kusano 7d535a
                    order = FILLORDER_MSB2LSB;
kusano 7d535a
                    initImage();
kusano 7d535a
                    break;
kusano 7d535a
                case 'w':                       /* photometric MinIsWhite */
kusano 7d535a
                    photo = PHOTOMETRIC_MINISWHITE;
kusano 7d535a
                    initImage();
kusano 7d535a
                    break;
kusano 7d535a
                case 'W':                       /* toggle warnings */
kusano 7d535a
                    owarning = TIFFSetWarningHandler(owarning);
kusano 7d535a
                    initImage();
kusano 7d535a
                    break;
kusano 7d535a
                case 'E':                       /* toggle errors */
kusano 7d535a
                    oerror = TIFFSetErrorHandler(oerror);
kusano 7d535a
                    initImage();
kusano 7d535a
                    break;
kusano 7d535a
                case 'z':                       /* reset to defaults */
kusano 7d535a
                case 'Z':
kusano 7d535a
                    order = order0;
kusano 7d535a
                    photo = photo0;
kusano 7d535a
                    if (owarning == NULL)
kusano 7d535a
                        owarning = TIFFSetWarningHandler(NULL);
kusano 7d535a
                    if (oerror == NULL)
kusano 7d535a
                        oerror = TIFFSetErrorHandler(NULL);
kusano 7d535a
                    initImage();
kusano 7d535a
                    break;
kusano 7d535a
                case 'q':                       /* exit */
kusano 7d535a
                case '\033':
kusano 7d535a
                    cleanup_and_exit();
kusano 7d535a
        }
kusano 7d535a
        glutPostRedisplay();
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
static void
kusano 7d535a
raster_special(int key, int x, int y)
kusano 7d535a
{
kusano 7d535a
        switch (key) {
kusano 7d535a
                case GLUT_KEY_PAGE_UP:          /* previous logical image */
kusano 7d535a
                    if (TIFFCurrentDirectory(tif) > 0) {
kusano 7d535a
                            if (TIFFSetDirectory(tif,
kusano 7d535a
                                                 TIFFCurrentDirectory(tif)-1)) {
kusano 7d535a
                                    initImage();
kusano 7d535a
                                    setWindowSize();
kusano 7d535a
                        }
kusano 7d535a
                    } else {
kusano 7d535a
                            TIFFRGBAImageEnd(&img);
kusano 7d535a
                            prevImage();
kusano 7d535a
                            initImage();
kusano 7d535a
                            setWindowSize();
kusano 7d535a
                    }
kusano 7d535a
                break;
kusano 7d535a
                case GLUT_KEY_PAGE_DOWN:        /* next logical image */
kusano 7d535a
                    if (!TIFFLastDirectory(tif)) {
kusano 7d535a
                            if (TIFFReadDirectory(tif)) {
kusano 7d535a
                                    initImage();
kusano 7d535a
                                    setWindowSize();
kusano 7d535a
                            }
kusano 7d535a
                    } else {
kusano 7d535a
                            TIFFRGBAImageEnd(&img);
kusano 7d535a
                            nextImage();
kusano 7d535a
                            initImage();
kusano 7d535a
                            setWindowSize();
kusano 7d535a
                    }
kusano 7d535a
                break;
kusano 7d535a
                case GLUT_KEY_HOME:             /* 1st image in current file */
kusano 7d535a
                        if (TIFFSetDirectory(tif, 0)) {
kusano 7d535a
                                TIFFRGBAImageEnd(&img);
kusano 7d535a
                                initImage();
kusano 7d535a
                                setWindowSize();
kusano 7d535a
                        }
kusano 7d535a
                break;
kusano 7d535a
                case GLUT_KEY_END:              /* last image in current file */
kusano 7d535a
                        TIFFRGBAImageEnd(&img);
kusano 7d535a
                        while (!TIFFLastDirectory(tif))
kusano 7d535a
                                TIFFReadDirectory(tif);
kusano 7d535a
                        initImage();
kusano 7d535a
                        setWindowSize();
kusano 7d535a
                break;
kusano 7d535a
        }
kusano 7d535a
        glutPostRedisplay();
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
kusano 7d535a
char* stuff[] = {
kusano 7d535a
"usage: tiffgt [options] file.tif",
kusano 7d535a
"where options are:",
kusano 7d535a
" -c            use colormap visual",
kusano 7d535a
" -d dirnum     set initial directory (default is 0)",
kusano 7d535a
" -e            enable display of TIFF error messages",
kusano 7d535a
" -l            force lsb-to-msb FillOrder",
kusano 7d535a
" -m            force msb-to-lsb FillOrder",
kusano 7d535a
" -o offset     set initial directory offset",
kusano 7d535a
" -p photo      override photometric interpretation",
kusano 7d535a
" -r            use fullcolor visual",
kusano 7d535a
" -s            stop decoding on first error (default is ignore errors)",
kusano 7d535a
" -v            enable verbose mode",
kusano 7d535a
" -w            enable display of TIFF warning messages",
kusano 7d535a
NULL
kusano 7d535a
};
kusano 7d535a
kusano 7d535a
static void
kusano 7d535a
usage(void)
kusano 7d535a
{
kusano 7d535a
        char buf[BUFSIZ];
kusano 7d535a
        int i;
kusano 7d535a
kusano 7d535a
        setbuf(stderr, buf);
kusano 7d535a
                fprintf(stderr, "%s\n\n", TIFFGetVersion());
kusano 7d535a
        for (i = 0; stuff[i] != NULL; i++)
kusano 7d535a
                fprintf(stderr, "%s\n", stuff[i]);
kusano 7d535a
        exit(-1);
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
static uint16
kusano 7d535a
photoArg(const char* arg)
kusano 7d535a
{
kusano 7d535a
        if (strcmp(arg, "miniswhite") == 0)
kusano 7d535a
            return (PHOTOMETRIC_MINISWHITE);
kusano 7d535a
        else if (strcmp(arg, "minisblack") == 0)
kusano 7d535a
            return (PHOTOMETRIC_MINISBLACK);
kusano 7d535a
        else if (strcmp(arg, "rgb") == 0)
kusano 7d535a
            return (PHOTOMETRIC_RGB);
kusano 7d535a
        else if (strcmp(arg, "palette") == 0)
kusano 7d535a
            return (PHOTOMETRIC_PALETTE);
kusano 7d535a
        else if (strcmp(arg, "mask") == 0)
kusano 7d535a
            return (PHOTOMETRIC_MASK);
kusano 7d535a
        else if (strcmp(arg, "separated") == 0)
kusano 7d535a
            return (PHOTOMETRIC_SEPARATED);
kusano 7d535a
        else if (strcmp(arg, "ycbcr") == 0)
kusano 7d535a
            return (PHOTOMETRIC_YCBCR);
kusano 7d535a
        else if (strcmp(arg, "cielab") == 0)
kusano 7d535a
            return (PHOTOMETRIC_CIELAB);
kusano 7d535a
        else if (strcmp(arg, "logl") == 0)
kusano 7d535a
            return (PHOTOMETRIC_LOGL);
kusano 7d535a
        else if (strcmp(arg, "logluv") == 0)
kusano 7d535a
            return (PHOTOMETRIC_LOGLUV);
kusano 7d535a
        else
kusano 7d535a
            return ((uint16) -1);
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
/* vim: set ts=8 sts=8 sw=8 noet: */
kusano 7d535a
/*
kusano 7d535a
 * Local Variables:
kusano 7d535a
 * mode: c
kusano 7d535a
 * c-basic-offset: 8
kusano 7d535a
 * fill-column: 78
kusano 7d535a
 * End:
kusano 7d535a
 */