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